首页 > 技术文章 > 关于 DotNetCore 的自定义权限管理

citycomputing 2018-11-30 15:04 原文

 

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

 

推荐阅读