- A+
所属分类:.NET技术
Program.cs
#region 授权 builder.Services.AddAuthorization(option => { //添加自定义授权策略 option.AddPolicy("MyPolicy",p => p.RequireClaim(ClaimTypes.NameIdentifier,"1")); }); #endregion
TestController.cs 应用自定义授权策略
[ApiController] [Route("api/[controller]")] public class TestController : ControllerBase { [Authorize("MyPolicy")] [HttpGet] public async Task<string> Get() { return await Task.FromResult(DateTime.Now.ToString()); } }
TokenAuthenticationHandler.cs
public Task<AuthenticateResult> AuthenticateAsync() { string token = _context.Request.Headers["Authorization"]; if (token == "test") { ClaimsIdentity identity = new ClaimsIdentity("Ctm"); identity.AddClaims(new List<Claim>(){ new Claim(ClaimTypes.Name,"admin"), new Claim(ClaimTypes.NameIdentifier,"6") }); var claimsPrincipal = new ClaimsPrincipal(identity); return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, null, _scheme.Name))); } return Task.FromResult(AuthenticateResult.Fail("token错误,请重新登录")); } /// <summary> /// 没有权限访问 /// </summary> /// <param name="properties"></param> /// <returns></returns> /// <exception cref="NotImplementedException"></exception> public Task ForbidAsync(AuthenticationProperties? properties) { _context.Response.StatusCode = 403; return Task.CompletedTask; }
此处鉴权给的值是6,授权用的1,尝试访问
重要概念
基于策略的授权中有一个很重要的概念是Requirements,每一个Requirement都代表一个授权条件。
Requirement需要继承接口IAuthorizationRequirement。
已经内置了一些常用的实现:
AssertionRequirement :使用最原始的断言形式来声明授权策略。
DenyAnonymousAuthorizationRequirement :用于表示禁止匿名用户访问的授权策略,并在AuthorizationOptions中将其设置为默认策略。
ClaimsAuthorizationRequirement :用于表示判断Cliams中是否包含预期的Claims的授权策略。
RolesAuthorizationRequirement :用于表示使用ClaimsPrincipal.IsInRole来判断是否包含预期的Role的授权策略。
NameAuthorizationRequirement:用于表示使用ClaimsPrincipal.Identities.Name来判断是否包含预期的Name的授权策略。
OperationAuthorizationRequirement:用于表示基于操作的授权策略。
当内置的Requirement不能满足需求时,可以定义自己的Requirement.
自定义Requirement
builder.Services.AddAuthorization(option => { option.AddPolicy("MyPolicy",p => p.Requirements.Add(new MyAuthorizationHandler("1"))); });
MyAuthorizationHandler.cs
public class MyAuthorizationHandler : AuthorizationHandler<MyAuthorizationHandler>, IAuthorizationRequirement { private readonly string _userId; public MyAuthorizationHandler(string userId) { _userId = userId; } protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MyAuthorizationHandler requirement) { if (context.User.HasClaim(c => c.Type == ClaimTypes.NameIdentifier) && context.User.Claims.FirstOrDefault(c => c.Type.Equals(ClaimTypes.NameIdentifier)).Value == _userId) { context.Succeed(requirement); } else { context.Fail(); } return Task.CompletedTask; } }
多授权方案
builder.Services.AddAuthorization(option => { option.AddPolicy("MyPolicy",p => p.Requirements.Add(new MyAuthorizationHandler("1"))); option.AddPolicy("MyPolicy1", p => p.Requirements.Add(new MyAuthorizationHandler1("admin"))); });
MyAuthorizationHandler1.cs
public class MyAuthorizationHandler1 : AuthorizationHandler<MyAuthorizationHandler1>, IAuthorizationRequirement { private readonly string _userName; public MyAuthorizationHandler1(string userName) { _userName = userName; } protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MyAuthorizationHandler1 requirement) { if (context.User.HasClaim(c => c.Type == ClaimTypes.Name) && context.User.Claims.FirstOrDefault(c => c.Type.Equals(ClaimTypes.Name)).Value == _userName) { context.Succeed(requirement); } else { context.Fail(); } return Task.CompletedTask; } }
TestController.cs
[ApiController] [Route("api/[controller]")] public class TestController : ControllerBase { [Authorize(Policy = "MyPolicy")] [Authorize(Policy = "MyPolicy1")] [HttpGet] public async Task<string> Get() { return await Task.FromResult(DateTime.Now.ToString()); } }
鉴权方案 TokenAuthenticationHandler.cs
public class TokenAuthenticationHandler : IAuthenticationHandler { private AuthenticationScheme _scheme; private HttpContext _context; /// <summary> /// 鉴权初始化 /// </summary> /// <param name="scheme">鉴权架构名称</param> /// <param name="context">HttpContext</param> /// <returns></returns> /// <exception cref="NotImplementedException"></exception> public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) { _scheme = scheme; _context = context; return Task.CompletedTask; } public Task<AuthenticateResult> AuthenticateAsync() { string token = _context.Request.Headers["Authorization"]; if (token == "test") { ClaimsIdentity identity = new ClaimsIdentity("Ctm"); identity.AddClaims(new List<Claim>(){ new Claim(ClaimTypes.Name,"admin"), new Claim(ClaimTypes.NameIdentifier,"1") }); var claimsPrincipal = new ClaimsPrincipal(identity); return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, null, _scheme.Name))); } return Task.FromResult(AuthenticateResult.Fail("token错误,请重新登录")); } /// <summary> /// 未登录 /// </summary> /// <param name="properties"></param> /// <returns></returns> /// <exception cref="NotImplementedException"></exception> public Task ChallengeAsync(AuthenticationProperties? properties) { _context.Response.Redirect("/api/Login/NoLogin"); return Task.CompletedTask; } /// <summary> /// 没有权限访问 /// </summary> /// <param name="properties"></param> /// <returns></returns> /// <exception cref="NotImplementedException"></exception> public Task ForbidAsync(AuthenticationProperties? properties) { _context.Response.StatusCode = 403; return Task.CompletedTask; } }