ASP.NET MVC5(五):身份驗證、授權


使用Authorize特性進行身份驗證


  通常情況下,應用程序都是要求用戶登錄系統之后才能訪問某些特定的部分。在ASP.NET MVC中,可以通過使用Authorize特性來實現,甚至可以對整個應用程序全局使用Authorize特性。

Authorize的用法

本節以一個添加產品的示例來說明Authorize的使用方法。首先,創建Product類、添加屬性(如下所示)並創建ProductsController(MVC5 Controller with views,using Entity Framework)。

public class Product
{
    //產品編號
    public int Id { get; set; }
    //產品名稱
    public string ProductName { get; set; }
    //產品描述
    public string Description { get; set; }
    //產品價格
    public decimal Price { get; set; }
}

運行程序,將Url定位到/Products/Create,添加如下產品。

此時收到用戶需求,必須是已經登錄的用戶才可以添加產品,如匿名用戶請求訪問產品創建頁面,則直接定位到登錄界面。修改ProdutsController,只需要在Create動作上添加Authorize特性。

	[Authorize]
    public ActionResult Create()
    {
        return View();
    }

這時,我們在未登錄狀態下請求訪問產品創建頁面時,系統自動跳轉到登錄頁面。下面,我們來看一看Authorize特性的的工作原理。當用戶請求一個Action時,會調用OnAuthorization方法:

	public virtual void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        if (OutputCacheAttribute.IsChildActionCacheActive(filterContext))
        {
            // If a child action cache block is active, we need to fail immediately, even if authorization
            // would have succeeded. The reason is that there's no way to hook a callback to rerun
            // authorization before the fragment is served from the cache, so we can't guarantee that this
            // filter will be re-run on subsequent requests.
            throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache);
        }

        bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true)
                                 || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true);

        if (skipAuthorization)
        {
            return;
        }

        if (AuthorizeCore(filterContext.HttpContext))
        {
            // ** IMPORTANT **
            // Since we're performing authorization at the action level, the authorization code runs
            // after the output caching module. In the worst case this could allow an authorized user
            // to cause the page to be cached, then an unauthorized user would later be served the
            // cached page. We work around this by telling proxies not to cache the sensitive page,
            // then we hook our custom authorization code into the caching mechanism so that we have
            // the final say on whether a page should be served from the cache.

            HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
            cachePolicy.SetProxyMaxAge(new TimeSpan(0));
            cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
        }
        else
        {
            HandleUnauthorizedRequest(filterContext);
        }
    }

skipAuthorization代表是否跳過驗證,如果Action或Controller定義了AllowAnonymous特性,則跳過驗證。若不跳過驗證,則會判斷AuthorizeCore方法的執行結果,再來看看AuthorizeCore方法的源碼:

	protected virtual bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException("httpContext");
        }

        IPrincipal user = httpContext.User;
        if (!user.Identity.IsAuthenticated)
        {
            return false;
        }

        if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
        {
            return false;
        }

        if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
        {
            return false;
        }

        return true;
    }

如果用戶沒有登錄,則返回False;如果用戶組長度大於0且不包括當前用戶,則返回False;如果授權角色長度大於0且不包含當前用戶,返回False;否則返回True 。

★Authorize特性不僅可以用在Action上,同樣可以使用在Controller上

全局授權過濾器

  對於大部分網站而言,基本上整個應用程序都需要身份驗證,當然我們不可能在每個控制器上添加Authorize特性。此時,把AuthorizeAttribute配置為全局過濾器,並使用AllowAnonymous特性來允許匿名訪問某些控制器或方法。修改App_Start/FilterConfig.cs文件中的RegisterGlobalFilters方法:

 	public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new AuthorizeAttribute());
        filters.Add(new HandleErrorAttribute());
    }

注意,在AccountController中的Login方法,系統已經幫我們添加了AllowAnonymous特性,不然是無法正常登陸的。

 	[AllowAnonymous]
    public ActionResult Login(string returnUrl)
    {
        ViewBag.ReturnUrl = returnUrl;
        return View();
    }

##授權

使用Authorize特性限定用戶或角色的訪問

  目前為止,已經介紹了使用Authorize特性禁止匿名用戶訪問控制器或方法。同樣的,我們也可以使用Authorize特性來限定特定用戶或角色的訪問。上一節中的示例,新增只有Administrator角色用戶才能夠編輯產品的功能。

	[Authorize(Roles ="Administrator")]
    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Product product = db.Products.Find(id);
        if (product == null)
        {
            return HttpNotFound();
        }
        return View(product);
    }

當然,我們也可以通過指定用戶的方式來限定訪問:

	[Authorize(Users = "Jack,Mike,July")]
    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Product product = db.Products.Find(id);
        if (product == null)
        {
            return HttpNotFound();
        }
        return View(product);
    }


免責聲明!

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



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