当前位置: 首页 > 科技观察

.NETCore授权失败如何自定义响应信息?

时间:2023-03-13 00:52:22 科技观察

本文转载自微信公众号“JeffckyShare”,作者Jeffcky。转载请联系JeffckyShare公众号.这篇文章我们来看看为什么.NET5中会有授权失败的中间件接口?它是如何一步步推导出来的?以及如何根据实际需要自定义授权失败的响应错误,以及如何获取相应的路由信息??等授权失败自定义响应信息如下是在.NET5之前,对于授权处理,我们大多数实现自定义的AuthorizationHandlerHandlerpublicclassCustomAuthorization:AuthorizationHandler{protectedoverrideTaskHandleRequirementAsync(AuthorizationHandlerContextcontext,CustomAuthorizationRequirementrequirement){thrownewNotImplementedException();}}publicclassCustomAuthorizationRequirement:IAuthorizationRequirement{publicCustomAuthorizationRequirement(){}}但是这个时候参数给的是授权上下文,我们在里面获取不到相关信息当前请求上下文。如果是mvc里面,大部分肯定是protectedoverrideTaskHandleRequirementAsync(AuthorizationHandlerContextcontext,CustomAuthorizationRequirementrequirement){varcontext=context.ResourceasHttpContext;}但是对于前后端分离的webapi,我没记错的话,获取的值为空,所以我们通过注入context接口来实现,演化为如下publicclassCustomAuthorizeHandler:AuthorizationHandler{privatereadonlyIHttpContextAccessor_accessor;publicCustomAuthorizeHandler(IHttpContextAccessoraccessor){_accessor=accessor;}protectedasyncoverrideTaskHandleRequirementAsync(AuthorizationHandlerContextcontext,CustomAuthorizationRequirementrequirement){varhttpContext=_accessor.HttpContext;//授权失败响应信息awaithttpContext.Response.WriteAsync("Authorizationfailurecall");/}}通过上下文,我们可以得到用户声明信息等信息,貌似基本满足了我们的实际业务需求,那如果要获取路由信息怎么办呢?3.0以下好像只能通过Path本身来解析(个人猜测),在.NETCore3.0+上,正式开放了context的扩展方法,为我们提供了路由节点元数据的详细信息。端点类中有一个元数据属性,它是一个集合,元数据包含你想要的任何东西。东东这里必须强调一下,我最喜欢.NETCore的地方就是很多时候我们会封装类库,在类库中使用WebAPI中所有相关的上下文信息等等。如果是以前的.NETFramework的话有点麻烦,比如如上获取类库中的context接口。如果还是沿用老思路,查看vssmart提示是否需要安装包,会发现WebAPI中的版本和你安装的版本不对应。这个可能有问题(具体细节我没深究),其实我要安装的是.NETCore类库中的.NET5。实现.NETCore相关基础框架信息,只需要在类库工程文件中引入配套的.NETCore应用包即可,使其与当前应用版本完全一致针对不同的读者群体,这里重点介绍下,以免童鞋在学习.NETCore时误入歧途!话题扯远了。例如,如上文所述,我们希望获取元数据中的控制器和动作名称。想要对应的信息,需要稍微清楚一点.NETCore基本流程处理所提供的各个对象publicclassCustomAuthorizeHandler:AuthorizationHandler{privatereadonlyIHttpContextAccessor_accessor;publicCustomAuthorizeHandler(IHttpContextAccessoraccessor){_accessor=accessor;}protectedasyncoverrideTaskHandleRequirementAsync(AuthorizationHandlerContextcontext,CustomAuthorizationRequirementrequirement){varhttpContext=_accessor.HttpContext;varendPoint=httpContext.GetEndpoint();varcontrollerActionDescriptor=(ControllerActionDescriptor)endPoint.Metadata.ToList().FirstOrDefault(d=>disControllerActionDescriptor);varcontrollerName=controllerActionDescriptor.ControllerName;varactionName=controllerActionDescriptor.ActionName;}}说到这里,实现相应的抽象授权处理对象,基本可以满足我们的需求。即使我们在上面获取到context和response,也无法获取到接口response,因为授权context只提供了Fail和Succeed方法。如果我们想在业务失败后直接响应呢?所以最大的问题在于:我们无法完全控制响应,自定义响应。这时,经过github上开发者的激烈反馈,.NET5官方给出了,用于授权处理的中间件接口,上下文也直接暴露了publicclassCustomAuthorizationMiddlewareResultHandler:IAuthorizationMiddlewareResultHandler{publicasyncTaskHandleAsync(RequestDelegatenext、HttpContextcontext、AuthorizationPolicypolicy、PolicyAuthorizationResultauthorizeResult){varendPoint=context.GetEndpoint();varcontrollerActionDescriptor=(ControllerActionDescriptor)endPoint.Metadata.ToList()。controllerActionDescriptor.ActionName;if(!context.User.Identity.IsAuthenticated){context.Response.StatusCode=(int)HttpStatusCode.Unauthorized;awaitcontext.Response.WriteAsync("{\"data\":{\"成功\":false,\"code\":401,\"message\":\"登录已过期,请重新登录\"}}");return;}elseif(!awaitHandleRequirementEvaluateAsync(context.User,controllerName,actionName)){context.Response.StatusCode=(int)HttpStatusCode.Forbidden;awaitcontext.Response.WriteAsync("{\"data\":{\"成功\":false,\"code\":403,\"message\":\"您没有足够的权限执行此操作\"}}");return;}awaitnext(context);}}自.NET5给我们授权中间件接口,一切都是那么的得心应手!