支付网站开发怎么做账,广州网站推广团队,wordpress 挖矿脚本,企业网络营销策划必须以什么为核心众所周知#xff0c;在Asp.net WebAPI中#xff0c;认证是通过AuthenticationFilter过滤器实现的#xff0c;我们通常的做法是自定义AuthenticationFilter#xff0c;实现认证逻辑#xff0c;认证通过#xff0c;继续管道处理#xff0c;认证失败#xff0c;直接返回认… 众所周知在Asp.net WebAPI中认证是通过AuthenticationFilter过滤器实现的我们通常的做法是自定义AuthenticationFilter实现认证逻辑认证通过继续管道处理认证失败直接返回认证失败结果类似如下 public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken) { var principal await this.AuthenticateAsync(context.Request); if (principal null) { context.Request.Headers.GetCookies().Clear(); context.ErrorResult new AuthenticationFailureResult(未授权请求, context.Request); } else { context.Principal principal; } } 但在.net core中AuthenticationFilter已经不复存在取而代之的是认证中间件。至于理由我想应该是微软觉得Authentication并非业务紧密相关的放在管道中间件中更合适。那么话说回来在.net core中我们应该怎么实现认证呢如大家所愿微软已经为我们提供了认证中间件。这里以CookieAuthenticationMiddleware中间件为例来介绍认证的实现。 1、引用Microsoft.AspNetCore.Authentication.Cookies包。项目实践中引用的是Microsoft.AspNetCore.Authentication.Cookies: 1.1.0。 2、Startup中注册及配置认证、授权服务 服务注册 services.AddMvc(options { //添加模型绑定过滤器 options.Filters.Add(typeof(ModelValidateActionFilter)); //添加授权过滤器以便强制执行Authentication跳转及屏蔽逻辑 //var policy new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build(); var policy new AuthorizationPolicyBuilder().AddRequirements(new AuthenticationRequirement()).Build(); options.Filters.Add(new AuthorizeFilter(policy)); }); //services.AddAuthorization(options //{ // options.AddPolicy(RequireAuthentication, policy policy.AddRequirements(new AuthenticationRequirement())); //}); 大家注意上面代码中有两处注释掉的地方。第一处注释RequireAuthenticatedUser()是.net core预定义的授权验证代表通过授权验证的最低要求是提供经过认证的Identity。Demo中我的要求也是这个只要是经过基本认证的用户即可那为什么Demo中没有使用呢因为这里是个坑实际实践中我发现采用注释中的做法无论如何调用总是返回401迫不得已download认证及授权源码发现该处逻辑是这样的 var user context.User; var userIsAnonymous user?.Identity null || !user.Identities.Any(i i.IsAuthenticated); if (!userIsAnonymous) { context.Succeed(requirement); } 加入断点猛调发现IsAuthenticated永远是false迫不得已反编译查看源码发现ClaimsIdentity的IsAuthenticated属性是这样定义的 WTF坑爹么这是.net framework中 记得 这里的逻辑是只要Name非空就返回true到了.net core中成了这样你说坑不坑。。。 那怎么办总不能放弃吧我想大家第一想法应该是继承ClaimsIdentity自定义一个Identity尤其是看到属性上那个virtual的时候我也不例外。可继承后 发现认证框架那儿依然不认还是一直返回false可能是我哪里用的不对吧。所以Startup中第一处注释出现了。最终解决方案是自定义AuthenticationRequirement及处理器实现要求的验证如下 public class AuthenticationRequirement : AuthorizationHandlerAuthenticationRequirement, IAuthorizationRequirement { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AuthenticationRequirement requirement) { var user context.User; var userIsAnonymous user?.Identity null || string.IsNullOrWhiteSpace(user.Identity.Name); if (!userIsAnonymous) { context.Succeed(requirement); } return TaskCache.CompletedTask; } } 上述代码红色的部分便是相对默认实现变化的部分。 startup中第二部分注释是注册授权策略的注册方法也是官网文档中给出的注册方法。那为什么这里又没有采用呢因为如果按注释中的方法配置我需要在每个希望认证的控制器或方法上都用Authorize标记甚至还需要在特性上配置角色或策略而这里我的预设是全局认证所以直接以全局过滤器的形式添加到了MVC处理管道中。读到这里细心的读者应该有疑问了你一个简单的认证跟授权毛线关系啊注册授权过滤器作甚我也觉得没关系啊这是net core认证的第二个坑那就是在.net core或者微软看来认证仅仅提供Principal的生成、序列化、反序列化及重新生成Principal它的职责确实也包括了返回401、403等各种认证失败信息但这部分不会主动触发必须有处理管道中其他逻辑去触发。我仔细阅读了官网文档得出的大致结论是.net core大概认为认证是个多样化的过程不光有我们目前看到的或需要的某一种认证实际需求中很可能会多种认证并存我们的API也可能会同时允许多种认证方式通过所以某一种认证失败就直接返回401或403是错误的。这是实践当中第二个坑那话说回来添加了授权就可以触发这个过程这个是看源码发现的具体流程就是如果授权失败过滤器会返回一个challengeResult这个Result最终会跑到认证中间件中的对应Challenge方法在.net core源码中表现如下 public async Task ChallengeAsync(ChallengeContext context) { ChallengeCalled true; var handled false; if (ShouldHandleScheme(context.AuthenticationScheme, Options.AutomaticChallenge)) { switch (context.Behavior) { case ChallengeBehavior.Automatic: // If there is a principal already, invoke the forbidden code path var result await HandleAuthenticateOnceSafeAsync(); if (result?.Ticket?.Principal ! null) { goto case ChallengeBehavior.Forbidden; } goto case ChallengeBehavior.Unauthorized; case ChallengeBehavior.Unauthorized: handled await HandleUnauthorizedAsync(context); Logger.AuthenticationSchemeChallenged(Options.AuthenticationScheme); break; case ChallengeBehavior.Forbidden: handled await HandleForbiddenAsync(context); Logger.AuthenticationSchemeForbidden(Options.AuthenticationScheme); break; } context.Accept(); } if (!handled PriorHandler ! null) { await PriorHandler.ChallengeAsync(context); } } 以其中HandleForbiddenAsync为例具体又如下 /// summary/// Override this method to deal with a challenge that is forbidden. /// /summary/// param namecontext/paramprotected virtual Taskbool HandleForbiddenAsync(ChallengeContext context){Response.StatusCode 403; return Task.FromResult(true);} 这样经由授权流程触发ChallengeChallenge返回相应验证结果到API调用方。 注册完了认证及授权所需相关服务接下来注册中间件如下 app.UseCookieAuthentication(new CookieAuthenticationOptions{AuthenticationScheme GuoKun,AutomaticAuthenticate true,AutomaticChallenge true, DataProtectionProvider DataProtectionProvider.Create(new DirectoryInfo(env.ContentRootPath))});app.UseMvc(); 注意UseCookieAuthentication要放在UseMvc前面。大家注意其中红色部分这里为什么要自己手动创建DataProtectionProvider呢因为这里是要做服务集群的如果单机或单服务实例情况下采用默认DataProtection机制就可以了。代码中手动指定目录创建与默认实现的区别就是默认实现会生成一个与当前机器及应用相关的key进行数据加解密而手动指定目录创建provider会在指定的目录下生成一个key的xml文件。这样服务集群部署时候加解密key一样加解密得到的报文也是一致的。别问我怎么知道的踩过坑使劲儿调试外加看官网文档泪流满面。。。 3、添加控制器模拟登陆及认证授权 [Route(api/[controller])] public class AccountController : Controller{[AllowAnonymous][HttpPost(login)] public async Task Login([FromBody]User user){IEnumerableClaim claims new ListClaim(){ new Claim(ClaimTypes.Name, user.UID)}; await HttpContext.Authentication.SignInAsync(GuoKun, new ClaimsPrincipal(new ClaimsIdentity(claims)));}[HttpGet(serverresponse)] public ContentResult ServerResponse(){ return this.Content($来自{((Microsoft.AspNetCore.Server.Kestrel.Internal.Http.ConnectionContext)this.HttpContext.Features).LocalEndPoint.ToString()}的响应{this.User.Identity.Name ?? 匿名}您好);}} 因为现在是全局的所以在登陆方法上用AllowAnonymous标记跳过认证及授权。 在ServerResponse方法中返回当前服务实例绑定的IP及端口号。由于本Demo是采用ANCM寄宿在IIS中的所以具体服务实例绑定的端口是动态的。 4、部署。具体在IIS中的部署如下 三个站点的端口分别为9001,9002,9003具体运行时ANCM会将IIS的请求代理到KestrlServer。 5、Nginx负载均衡配置 upstream guokun {server localhost:9001;server localhost:9002;server localhost:9003;}server {listen 9000;server_name localhost;#charset koi8-r;#access_log logs/host.access.log main;location / {root html;index index.html index.htm;proxy_pass http://guokun;} 这个比较简单不废话。 6、运行效果 这里采用Postman模拟请求。当未调用登录API直接请求api/Account/serverresponse时如下 可以看到直接401了而且响应标头中有个Location这个是challenge中默认实现的告诉我们需要去登录认证认证完了会跳转到当前请求资源url在MVC中尤其有用。 接下来登录 我们可以看到登录成功而且服务端返回了加密及序列化后的凭证。接下来我们再请求api/Account/serverresponse 看到没请求成功。那么多请求几次分别得到如下结果 可以看见请求已经被负载到了不同的服务实例。 有人会问为什么不部署在多台不同服务器上啊搞一台机器在那儿模拟。哥没那么多钱整那么多台机器啊而且装虚拟机配置撑不了望大神勿喷勿吐槽。 如此一个简易的基于asp.net core带认证具有集群负载的后端便实现了。 相关文章 .NET Core中的认证管理解析ASP.NET Core 之 Identity 入门一ASP.NET Core 之 Identity 入门二ASP.NET Core 之 Identity 入门三ASP.NET Core 中的那些认证中间件及一些重要知识点 原文地址http://www.cnblogs.com/guokun/p/6266558.html.NET社区新闻深度好文微信中搜索dotNET跨平台或扫描二维码关注