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、參考資料
《ASP.NET Core 2.0 authentication middleware》