1、自定义权限需要扩展 Microsoft.AspNetCore.Authentication 实现一套接口
IAuthenticationHandler, IAuthenticationSignInHandler, IAuthenticationSignOutHandler
public class MyAuthenticationHandler : IAuthenticationHandler, IAuthenticationSignInHandler, IAuthenticationSignOutHandler { public AuthenticationScheme Scheme { get; private set; } protected HttpContext Context { get; private set; } public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context) { Scheme = scheme; Context = context; return Task.CompletedTask; } public Task ChallengeAsync(AuthenticationProperties properties) { Context.Response.Redirect("/Account/login"); return Task.CompletedTask; } public async Task<AuthenticateResult> AuthenticateAsync() { var result = await Task.Run<AuthenticateResult>(() => { var cookie = Context.Request.Cookies["myCookie"]; if (string.IsNullOrEmpty(cookie)) { return AuthenticateResult.NoResult(); } return AuthenticateResult.Success(this.Deserialize(cookie)); }); return result; } public Task ForbidAsync(AuthenticationProperties properties) { Context.Response.StatusCode = 403; return Task.CompletedTask; } public Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties) { var ticket = new AuthenticationTicket(user, properties, Scheme.Name); Context.Response.Cookies.Append("myCookie", Serialize(ticket)); return Task.CompletedTask; } public Task SignOutAsync(AuthenticationProperties properties) { Context.Response.Cookies.Delete("myCookie"); return Task.CompletedTask; } private string Serialize(AuthenticationTicket ticket) { byte[] byteTicket = TicketSerializer.Default.Serialize(ticket); return System.Text.Encoding.Default.GetString(byteTicket); } private AuthenticationTicket Deserialize(string ticket) { byte[] byteTicket = System.Text.Encoding.Default.GetBytes(ticket); return TicketSerializer.Default.Deserialize(byteTicket); } }
2、在 ConfigureServices 中注册服务
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddAuthentication( option => { option.DefaultScheme = "myScheme"; option.AddScheme<MyAuthenticationHandler>("myScheme", "demo scheme"); }); services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddSession(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
3、在 void Configure(IApplicationBuilder app, IHostingEnvironment env) 中使用权限检查
app.UseAuthentication();
4、在 Controller 中实现自己的 Login 、Logout
[AllowAnonymous] public async void Login(string username, string password) { var claimIdentity = new ClaimsIdentity("CustomApiKeyAuth"); claimIdentity.AddClaim(new Claim(ClaimTypes.Name, username)); claimIdentity.AddClaim(new Claim(ClaimTypes.Role, "Admin")); await HttpContext.SignInAsync("myScheme", new ClaimsPrincipal(claimIdentity)); await HttpContext.Response.WriteAsync($"Hello {username} login!"); } public async void Logout() { await HttpContext.SignOutAsync("myScheme"); }
5、在 Controller 中使用权限检查特性
[Authorize(Roles = "Admin")] public void Test() { var user = HttpContext.User; HttpContext.Response.WriteAsync($"Test {user.Identity.Name}!"); }
6、测试
在浏览器上输入 https://localhost:44318/account/login?username="aaa"
系统输出: Hello "aaa" login!
在浏览器上输入 https://localhost:44318/account/test
系统输出 : Test "aaa"!
成功运行了。
7、结束语
虽然只是简单的框架代码,但实现了完整的流程控制。方便初学者。
需要源代码的朋友点这里下载。
8、参考资料