真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

asp.netcore策略授權(quán)

在《asp.net core認(rèn)證與授權(quán)》中講解了固定和自定義角色授權(quán)系統(tǒng)權(quán)限,其實(shí)我們還可以通過(guò)其他方式來(lái)授權(quán),比如可以通過(guò)角色組,用戶名,生日等,但這些主要取決于ClaimTypes,其實(shí)我們也可以自定義鍵值來(lái)授權(quán),這些統(tǒng)一叫策略授權(quán),其中更強(qiáng)大的是,我們可以自定義授權(quán)Handler來(lái)達(dá)到靈活授權(quán),下面一一展開(kāi)。

公司主營(yíng)業(yè)務(wù):成都網(wǎng)站建設(shè)、成都做網(wǎng)站、移動(dòng)網(wǎng)站開(kāi)發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開(kāi)放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來(lái)驚喜。創(chuàng)新互聯(lián)推出九江免費(fèi)做網(wǎng)站回饋大家。

注意:下面的代碼只是部分代碼,完整代碼參照:https://github.com/axzxs2001/Asp.NetCoreExperiment/tree/master/Asp.NetCoreExperiment/%E6%9D%83%E9%99%90%E7%AE%A1%E7%90%86/PolicyPrivilegeManagement

首先看基于角色組,或用戶名,或基于ClaimType或自定義鍵值等授權(quán)策略,這些都是通過(guò)Services.AddAuthorization添加,并且是AuthorizationOptions來(lái)AddPolicy,這里策略的名稱統(tǒng)一用RequireClaim來(lái)命名,不同的請(qǐng)求的策略名稱各不相同,如用戶名時(shí)就用policy.RequireUserName(),同時(shí),在登錄時(shí),驗(yàn)證成功后,要添加相應(yīng)的Claim到ClaimsIdentity中:

Startup.cs

       public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddAuthorization(options =>
            {
                //基于角色的策略
                 options.AddPolicy("RequireClaim", policy => policy.RequireRole("admin", "system"));
                //基于用戶名
                //options.AddPolicy("RequireClaim", policy => policy.RequireUserName("桂素偉"));
                //基于Claim
                //options.AddPolicy("RequireClaim", policy => policy.RequireClaim(ClaimTypes.Country,"中國(guó)"));
                //自定義值
                // options.AddPolicy("RequireClaim", policy => policy.RequireClaim("date","2017-09-02"));

            }).AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>{
                options.LoginPath = new PathString("/login");
                options.AccessDeniedPath = new PathString("/denied");
            });          
        }

HomeController.cs

using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using PolicyPrivilegeManagement.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.Security.Claims;
namespace PolicyPrivilegeManagement.Controllers
{
    [Authorize(Policy = "RequireClaim")]
    public class HomeController : Controller
    {
        PermissionHandler _permissionHandler;
        public HomeController(IAuthorizationHandler permissionHandler)
        {
            _permissionHandler = permissionHandler as PermissionHandler;
        }
        public IActionResult Index()
        {
            return View();
        }
        public IActionResult PermissionAdd()
        {           
            return View();
        }

        public IActionResult Contact()
        {
            ViewData["Message"] = "Your contact page.";
            return View();
        }
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
        [AllowAnonymous]
        [HttpGet("login")]
        public IActionResult Login(string returnUrl = null)
        {
            TempData["returnUrl"] = returnUrl;
            return View();
        }
        [AllowAnonymous]
        [HttpPost("login")]
        public async Task Login(string userName, string password, string returnUrl = null)
        {
            var list = new List {
                new { UserName = "gsw", Password = "111111", Role = "admin",Name="桂素偉",Country="中國(guó)",Date="2017-09-02",BirthDay="1979-06-22"},
                new { UserName = "aaa", Password = "222222", Role = "system",Name="測(cè)試A" ,Country="美國(guó)",Date="2017-09-03",BirthDay="1999-06-22"}
            };
            var user = list.SingleOrDefault(s => s.UserName == userName && s.Password == password);
            if (user != null)
            {
                //用戶標(biāo)識(shí)
                var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
                identity.AddClaim(new Claim(ClaimTypes.Sid, userName));
                identity.AddClaim(new Claim(ClaimTypes.Name, user.Name));
                identity.AddClaim(new Claim(ClaimTypes.Role, user.Role));
                identity.AddClaim(new Claim(ClaimTypes.Country, user.Country));
                identity.AddClaim(new Claim("date", user.Date));
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity));
                if (returnUrl == null)
                {
                    returnUrl = TempData["returnUrl"]?.ToString();
                }
                if (returnUrl != null)
                {
                    return Redirect(returnUrl);
                }
                else
                {
                    return RedirectToAction(nameof(HomeController.Index), "Home");
                }
            }
            else
            {
                const string badUserNameOrPasswordMessage = "用戶名或密碼錯(cuò)誤!";
                return BadRequest(badUserNameOrPasswordMessage);
            }
        }
        [HttpGet("logout")]
        public async Task Logout()
        {
            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            return RedirectToAction("Index", "Home");
        }
        [AllowAnonymous]
        [HttpGet("denied")]
        public IActionResult Denied()
        {
            return View();
        }
    }
}

上面的授權(quán)策略都相對(duì)簡(jiǎn)單,單一,使用場(chǎng)景也很有限,就和固定角色授權(quán)如出一轍,其實(shí)可以用更好的來(lái)例用授權(quán),那就是自定義授權(quán)Handler,我們?cè)凇禷sp.net core認(rèn)證與授權(quán)》一文中,是通過(guò)中間件來(lái)達(dá)到自定義解色的,現(xiàn)在我們換個(gè)思路,通過(guò)自定義授權(quán)Handler來(lái)實(shí)現(xiàn)。

首先定義一個(gè)UserPermission,即用戶權(quán)限實(shí)體類

    /// 
    /// 用戶權(quán)限
    /// 
    public class UserPermission
    {
        /// 
        /// 用戶名
        /// 
        public string UserName
        { get; set; }
        /// 
        /// 請(qǐng)求Url
        /// 
        public string Url
        { get; set; }
    }

接下來(lái)定義一個(gè)PermissionRequirement,為請(qǐng)求條件實(shí)體類

    /// 
    /// 必要參數(shù)類
    /// 
    public class PermissionRequirement : IAuthorizationRequirement
    {
        /// 
        /// 用戶權(quán)限集合
        /// 
        public  List UserPermissions { get;private set; }
        /// 
        /// 無(wú)權(quán)限action
        /// 
        public string DeniedAction { get; set; }
        /// 
        /// 構(gòu)造
        /// 
        /// 無(wú)權(quán)限action
        /// 用戶權(quán)限集合
        public PermissionRequirement(string deniedAction, List userPermissions)
        {
            DeniedAction = deniedAction;
            UserPermissions = userPermissions;
        }
    }

再定義自定義授權(quán)Hanlder,我們命名為PermissionHandler,此類必需繼承AuthorizationHandler,只用實(shí)現(xiàn)public virtualTask HandleAsync(AuthorizationHandlerContext context),些方法是用戶請(qǐng)求時(shí)驗(yàn)證是否授權(quán)的主方法,所以實(shí)現(xiàn)與自定義角色中間件的Invoke很相似。

using Microsoft.AspNetCore.Authorization;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace PolicyPrivilegeManagement.Models
{
    /// 
    /// 權(quán)限授權(quán)Handler
    /// 
    public class PermissionHandler : AuthorizationHandler
    {
        /// 
        /// 用戶權(quán)限
        /// 
        public List UserPermissions { get; set; }
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
        {
            //賦值用戶權(quán)限
            UserPermissions = requirement.UserPermissions;
            //從AuthorizationHandlerContext轉(zhuǎn)成HttpContext,以便取出表求信息
            var httpContext = (context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext).HttpContext;
            //請(qǐng)求Url
            var questUrl = httpContext.Request.Path.Value.ToLower();
            //是否經(jīng)過(guò)驗(yàn)證
            var isAuthenticated = httpContext.User.Identity.IsAuthenticated;
            if (isAuthenticated)
            {
                if (UserPermissions.GroupBy(g => g.Url).Where(w => w.Key.ToLower() == questUrl).Count() > 0)
                {
                    //用戶名
                    var userName = httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Sid).Value;
                    if (UserPermissions.Where(w => w.UserName == userName && w.Url.ToLower() == questUrl).Count() > 0)
                    {
                        context.Succeed(requirement);
                    }
                    else
                    {
                        //無(wú)權(quán)限跳轉(zhuǎn)到拒絕頁(yè)面
                        httpContext.Response.Redirect(requirement.DeniedAction);
                    }
                }
                else
                {
                    context.Succeed(requirement);
                }
            }
            return Task.CompletedTask;
        }
    }
}

此次的Startup.cs的ConfigureServices發(fā)生了變化,如下

       public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddAuthorization(options =>
            {               
                //自定義Requirement,userPermission可從數(shù)據(jù)庫(kù)中獲得
                var userPermission = new List {
                              new UserPermission {  Url="/", UserName="gsw"},
                              new UserPermission {  Url="/home/permissionadd", UserName="gsw"},
                              new UserPermission {  Url="/", UserName="aaa"},
                              new UserPermission {  Url="/home/contact", UserName="aaa"}
                          };
                options.AddPolicy("Permission",
                          policy => policy.Requirements.Add(new PermissionRequirement("/denied", userPermission)));
            }).AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>{
                options.LoginPath = new PathString("/login");
                options.AccessDeniedPath = new PathString("/denied");
            });
            //注入授權(quán)Handler
            services.AddSingleton();
        }

HomeController中代碼如下:

using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using PolicyPrivilegeManagement.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.Security.Claims;
namespace PolicyPrivilegeManagement.Controllers
{
    [Authorize(Policy = "Permission")]
    public class HomeController : Controller
    {
        PermissionHandler _permissionHandler;
        public HomeController(IAuthorizationHandler permissionHandler)
        {
            _permissionHandler = permissionHandler as PermissionHandler;
        }
        public IActionResult Index()
        {
            return View();
        }
        public IActionResult PermissionAdd()
        {           
            return View();
        }
        [HttpPost("addpermission")]
        public IActionResult AddPermission(string url,string userName)
        {       
            //添加權(quán)限
            _permissionHandler.UserPermissions.Add(new UserPermission { Url = url, UserName = userName });
            return Content("添加成功");
        }
        
        public IActionResult Contact()
        {
            ViewData["Message"] = "Your contact page.";
            return View();
        }
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
        [AllowAnonymous]
        [HttpGet("login")]
        public IActionResult Login(string returnUrl = null)
        {
            TempData["returnUrl"] = returnUrl;
            return View();
        }
        [AllowAnonymous]
        [HttpPost("login")]
        public async Task Login(string userName, string password, string returnUrl = null)
        {
            var list = new List {
                new { UserName = "gsw", Password = "111111", Role = "admin",Name="桂素偉",Country="中國(guó)",Date="2017-09-02",BirthDay="1979-06-22"},
                new { UserName = "aaa", Password = "222222", Role = "system",Name="測(cè)試A" ,Country="美國(guó)",Date="2017-09-03",BirthDay="1999-06-22"}
            };
            var user = list.SingleOrDefault(s => s.UserName == userName && s.Password == password);
            if (user != null)
            {
                //用戶標(biāo)識(shí)
                var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
                identity.AddClaim(new Claim(ClaimTypes.Sid, userName));
                identity.AddClaim(new Claim(ClaimTypes.Name, user.Name));
                identity.AddClaim(new Claim(ClaimTypes.Role, user.Role));
                identity.AddClaim(new Claim(ClaimTypes.Country, user.Country));
                identity.AddClaim(new Claim("date", user.Date));
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity));
                if (returnUrl == null)
                {
                    returnUrl = TempData["returnUrl"]?.ToString();
                }
                if (returnUrl != null)
                {
                    return Redirect(returnUrl);
                }
                else
                {
                    return RedirectToAction(nameof(HomeController.Index), "Home");
                }
            }
            else
            {
                const string badUserNameOrPasswordMessage = "用戶名或密碼錯(cuò)誤!";
                return BadRequest(badUserNameOrPasswordMessage);
            }
        }
        [HttpGet("logout")]
        public async Task Logout()
        {
            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            return RedirectToAction("Index", "Home");
        }
        [AllowAnonymous]
        [HttpGet("denied")]
        public IActionResult Denied()
        {
            return View();
        }
    }
}

本例設(shè)計(jì)是當(dāng)用戶gsw密碼111111登錄時(shí),是不能訪問(wèn)/home/contact的,剛登錄時(shí)訪該action是不成功的,這里我們?cè)?home/addpermission中添加一個(gè)Action名稱:/home/contact,用戶名:gsw的信息,此時(shí)再訪問(wèn)/home/contact,會(huì)發(fā)現(xiàn)是可以訪問(wèn)的,這是因?yàn)槲覀儫岣铝薖ermissionHandler中的用戶權(quán)限集合,用戶的權(quán)限得到了擴(kuò)展和變化。

其實(shí)用中間件能達(dá)到靈活權(quán)限的設(shè)置,用自定義授權(quán)Handler也可以,接下來(lái)比較一下兩種做法的優(yōu)劣:


中間件

自定義授權(quán)Handler

用戶權(quán)限集合

靜態(tài)對(duì)象

實(shí)體化對(duì)象

熱更新時(shí)

用中間件名稱.用戶權(quán)限集合更新

因?yàn)樵赟tartup.cs中,PermissionHandler是依賴注放的,可以在熱更新的構(gòu)造中獲取并操作

性能方面

每個(gè)action請(qǐng)求都會(huì)觸發(fā)Invock方法,標(biāo)記[AllowAnonymous]特性的Action也會(huì)觸發(fā)

只有標(biāo)記[Authorize]特性的Action會(huì)觸發(fā)該方法,標(biāo)記[AllowAnonymous]特性的Action不會(huì)觸發(fā),性能更優(yōu)化

最后,把授權(quán)策略做了個(gè)NuGet的包,大家可在asp.net core 2.0的項(xiàng)目中查詢 AuthorizePolicy引用使用這個(gè)包,包對(duì)應(yīng)的github地址:https://github.com/axzxs2001/AuthorizePolicy,歡迎大家提出建議,來(lái)共同完善這個(gè)授權(quán)策略。


當(dāng)前標(biāo)題:asp.netcore策略授權(quán)
URL鏈接:http://weahome.cn/article/jhjcjj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部