【ASP.NET】ASP.NET中權限驗證使用OnAuthorization實現


在項目開發中,通常我們都會涉及到用戶登錄才能訪問的網頁,比如購物網站,我們瀏覽商品,添加購物車(以前開發的時候在這里就需要登錄用戶,但是現在有了緩存的實現,這里可以將商品加入緩存,等到結賬的時候再登錄),選擇結賬的時候需要登錄,那么這時候我們需要跳轉到登錄頁面登錄,登錄之后還可以回到記錄下來的原始的頁面,那么這之后我們有好幾種方法可以實現這種效果,下面筆者舉例兩種:

第一種:登錄模塊不管怎么樣都是統一的,就是在每個需要登錄的方法里面判斷用戶是否登錄,如果沒有登錄,則跳轉登錄,這種的缺點是工作量大,代碼冗余。

第二種:使用MVC的特性,定義類繼承IAuthorizationFilter,重寫OnAuthorization方法即可實現。此方法工作量少,代碼不冗余,如果需要登錄我們只需要給Controller或者Action給上標簽即可。

 

上面列舉了權限認證的兩種形式,在實際開發中使用OnAuthorization和特性相結合的情況比較多,在任何能夠使用特性的判斷中都可以按照下面的思路來實現,例如(登錄判斷,權限判斷,請求判斷,去除空格,讀取返回路徑)等等。

 接下來是筆者使用OnAuthorization的一個案例:

BaseController.cs

namespace MvcApplication1.Controllers
{
    public class BaseController : Controller
    {
        protected override void OnAuthorization(AuthorizationContext context)
        {
            //解析控制器的名稱
            string ControllerName = context.ActionDescriptor.ControllerDescriptor.ControllerName;
            if (ControllerName.ToLower() == "Manager".ToLower())//這里只對Manager的控制器進行權限驗證
            {
                var b = context.HttpContext.Request.Browser;//瀏覽器判斷 ie8 居然是7.0
                if (b.Browser == "IE" && float.Parse(b.Version) < 7)
                {
                    context.Result = Content("ie瀏覽器就只支持ie8+", "text/json");
                    return;
                }
                //解析出對應的方法
                var Method = context.Controller.GetType().GetMethods().Where(c => c.Name.ToLower() == context.ActionDescriptor.ActionName.ToLower()).FirstOrDefault();
                if (Method == null)
                {
                    context.Result = Content("權限不夠", "text/json");
                    return;
                }
                //解析出方法上面對應的特性
                AccessAttribute acc = Method.GetCustomAttributes(typeof(AccessAttribute), true).FirstOrDefault() as AccessAttribute;
                if (acc != null)
                {
                    if (acc.IsAccess == AccessEnum.Login)//需要登錄權限
                    {
                        if (!IsLogin())
                        {
                            context.HttpContext.Response.Redirect("~/Manager/Login");//如果沒有登錄,就跳轉到登錄頁面
                            return;
                        }
                    }
                    else if (acc.IsAccess == AccessEnum.Access)//需要其他權限
                    {
                        if (!IsAccess(context))
                        {
                            context.Result = Content("權限不夠", "text/json");
                            return;
                        }
                    }
                }
            }
            base.OnAuthorization(context);
        }
        /// <summary>
        /// 檢查是否登錄
        /// </summary>
        /// <returns>一個bool類型的數據,表示用戶是否登錄</returns>
        public bool IsLogin()
        {
            String userName = (String)System.Web.HttpContext.Current.Session["UserName"];
            String Password = (String)System.Web.HttpContext.Current.Session["Password"];
            if (System.Web.HttpContext.Current.Session["UserName"] != null)
            {
                if ("abc".Equals(userName) && "123".Equals(Password)) {
                    return true;
                }
            }
            else
            {
                    if (System.Web.HttpContext.Current.Request.Cookies["settings"] == null) {
                        return false;
                    }
                //檢查Cookies
                String cookie_UserName = System.Web.HttpContext.Current.Request.Cookies["settings"]["UserName"];
                String cookie_Password = System.Web.HttpContext.Current.Request.Cookies["settings"]["Password"];
                //檢查用戶名和密碼
                 if (cookie_UserName == null || cookie_Password == null)
                 {
                     return false;
                 }
                 else {
                     //在數據庫中檢查
                     if ("abc".Equals(cookie_UserName) && "123".Equals(cookie_Password)) {
                     //把用戶名和密碼放到Session中
                    Session.Add("UserName", cookie_UserName);
                    Session.Add("Password", cookie_Password);
                         return true;
                     }
                 }
            }
            return false;
        }
        /// <summary>
        /// 權限檢查
        /// </summary>
        /// <param name="context"></param>
        /// <returns>一個bool的數據,表示用戶是否擁有其他權限</returns>
        public bool IsAccess(AuthorizationContext context)
        {
            bool isAccess = false;

            var controller = context.RouteData.Values.Keys.First(p => p == "controller");
            var action = context.RouteData.Values.Keys.First(p => p == "action");
            var url = "/" + context.RouteData.Values[controller] + "/" + context.RouteData.Values[action];

            //根據controller和action 可以判斷權限了
            //isAccess = true;

            return isAccess;
        }
    }
}  
BaseController.cs

這里的BaseController類繼承了Controller,並且重寫了其中了OnAuthorization方法,在OnAuthorization方法中,首先解析出用戶請求的Controller名稱,然后判斷是否需要驗證這個Controller,案例中驗證的是名為Manager的Controller,得到了對應的Controller后,接下來解析用戶請求的具體是什么方法,再利用反射找出方法有什么特性,根據特性進行權限驗證。

 

ManagerController.cs

namespace MvcApplication1.Controllers
{
    public class ManagerController : BaseController
    {

        [Access(IsAccess = AccessEnum.Login)]
        public ActionResult Index()
        {
            return View("index");
        }

        [Access(IsAccess = AccessEnum.Anonymous)]
        public ActionResult ToLogin(){
            String user = Request["UserName"];
            String password = Request["Password"];
            if ("abc".Equals(user) && "123".Equals(password)) {
              //放到session中
                Session.Add("UserName", "abc");
                Session.Add("Password", "123");
                //放到Cookie中,可以進行加密處理
                HttpCookie myCookie = new HttpCookie("settings");
                myCookie["UserName"] = user;
                myCookie["Password"] = password;
                 System.Web.HttpContext.Current.Response.Cookies.Add(myCookie);
                 HttpContext.Response.Redirect("~/Manager/Index");
            }
            return View("Error");
        }

        [Access(IsAccess = AccessEnum.Anonymous)]
        public ActionResult Login()
        {
            return View();
        }
        [Access(IsAccess = AccessEnum.Login)]
        public ActionResult LoginOff(){
              //清除Session信息
              Session.Clear();
              //清除Cookie信息
              HttpCookie myCookie = new HttpCookie("settings");
              myCookie.Expires = DateTime.Now;
              System.Web.HttpContext.Current.Response.Cookies.Add(myCookie);
              HttpContext.Response.Redirect("~/Manager/index");
        }
    }
}    
ManagerController.cs

AccessAttribute.cs

namespace MvcApplication1.Models.Attribute
{
    /// <summary>
    /// <para>創建自定義權限認證特性</para>
    /// <para>該特性應用的范圍可以為類、構造方法、字段、方法、屬性</para>
    /// </summary>
    [AttributeUsage(AttributeTargets.Class |
     AttributeTargets.Constructor |
     AttributeTargets.Field |
     AttributeTargets.Method |
     AttributeTargets.Property,
     AllowMultiple = true)]
    public class AccessAttribute : System.Attribute
    {
        public AccessEnum IsAccess { set; get; }
    }

    /// <summary>
    /// 權限認證級別
    /// </summary>
    public enum AccessEnum
    {
        /// <summary>
        /// 權限認證
        /// </summary>
        Access,
        /// <summary>
        /// 只需要登錄
        /// </summary>
        Login,
        /// <summary>
        /// 不需要登錄
        /// </summary>
        Anonymous
    }
}
AccessAttribute.cs

Error.cshtml

@{
    ViewBag.Title = "error";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>賬號密碼錯誤</h2>
Error.cshtml

Index.cshtml

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>登錄成功,恭喜你登錄成功</h2>
Index.cshtml

Login.cshtml

@{
    ViewBag.Title = "登錄";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<div>
    <form action="tologin" method="post">
        <input type="text" name="UserName"/><br />
        <input type="password" name="Password" /><br/>
         <input type="submit" value="提交" />
    </form>
</div>
Login.cshtml

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM