.NET Core授权失败自定义响应信息的操作方法

前言

在.NET 5之前,当授权失败即403时无法很友好的自定义错误信息,以致于比如利用Vue获取到的是空响应,不能很好的处理实际业务,同时涉及到权限粒度控制到控制器、Action,也不能很好的获取对应路由信息。本文我们来看看在.NET 5中为何要出现针对授权失败的中间件接口?它是如何一步步衍生出来的呢?以及对于授权失败根据实际需要如何自定义响应错误,以及如何获取对应路由信息等等

授权失败自定义响应信息

如下是在.NET 5之前,对于授权处理,我们大多实现自定义的AuthorizationHandler

public class CustomAuthorizeHandler : AuthorizationHandler<CustomAuthorizationRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomAuthorizationRequirement requirement)
    {
        throw new NotImplementedException();
    }
}

public class CustomAuthorizationRequirement : IAuthorizationRequirement
{
    public CustomAuthorizationRequirement()
    {
    }
}

但此时参数给予的是授权上下文,我们并不能拿到当前请求上下文中的相关信息,如果是在mvc中,想必大多是如下这般获取的

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomAuthorizationRequirement requirement)
{
    var context = context.Resource as HttpContext;
}

但对于前后分离的web api中,若我没记错的话,这样是获取到的是空,于是乎我们借助于注入上下文接口实现,演变成如下这样

public class CustomAuthorizeHandler : AuthorizationHandler<CustomAuthorizationRequirement>
{
    private readonly IHttpContextAccessor _accessor;
    public CustomAuthorizeHandler(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }
    protected async override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomAuthorizationRequirement requirement)
    {
        var httpContext = _accessor.HttpContext;

        // 授权失败响应信息
        await httpContext.Response.WriteAsync("授权失败");

        //响应失败调用
        context.Fail();

    }
}

通过上下文可以拿到比如用户声明信息等等,貌似已经基本满足我们实际业务需求,那要是我想获取路由信息又该如何呢?在3.0以下貌似只能通过Path自己解析(个人猜测),从.NET Core 3.0+上,官方开放针对上下文的扩展方法,提供给我们获取路由节点元数据详细信息

在该终结点类存在一个元数据属性,该属性为集合,该元数据包含任何你想要的东东

这里必须强调一下,我最喜爱.NET Core的一点是,很多时候我们会封装类库,并在类库中使用到Web APi中相关的上下文一切信息等等,如果是以前.NET Framework怕是有点麻烦

比如如上在类库中获取上下文接口,如果你还是延续旧思想,查看vs智能提示你是否需要安装包,你会发现在Web APi中版本和你安装的版本是对应不上的,这可能是有问题的哈(具体细节我并未深入探究),但实际上我想安装的是.NET 5

在.NET Core类库中要实现.NET Core相关基础框架信息,只需要在类库项目文件中引入支持.NET Core应用程序包包即可,如此才和当前应用程序版本完全一致

<ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

面向不同群体读者,这里还是重点强调下,以免有些学习.NET Core的童鞋走偏了!话题扯远了,比如如上述我们想要获取到元数据中的控制器和action名称,该元数据集合参数都是object,所以我们想要对应的信息,需要稍微清楚一点.NET Core基本流程处理所提供的各个对象

public class CustomAuthorizeHandler : AuthorizationHandler<CustomAuthorizationRequirement>
{
    private readonly IHttpContextAccessor _accessor;
    public CustomAuthorizeHandler(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }
    protected async override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomAuthorizationRequirement requirement)
    {
        var httpContext = _accessor.HttpContext;

        var endPoint = httpContext.GetEndpoint();

        var controllerActionDescriptor = (ControllerActionDescriptor)endPoint.Metadata
            .ToList().FirstOrDefault(d => d is ControllerActionDescriptor);

        var controllerName = controllerActionDescriptor.ControllerName;

        var actionName = controllerActionDescriptor.ActionName;

    }
}

讲到这里,实现对应抽象授权处理对象,基本上可满足我们的需求,即使上述拿到上下文并响应,但是在接口响应上我们是获取不到的,因为授权上下文,只提供Fail和Succeed方法,要是我们想根据业务失败后直接响应呢?所以最大的问题出在:我们无法完全控制响应,以及自定义响应。这个时候,经过开发者在github上激烈的反馈,官方在.NET 5给出了,针对授权处理的中间件接口,上下文也已直接对外暴露

public class CustomAuthorizationMiddlewareResultHandler
        : IAuthorizationMiddlewareResultHandler
{

    public async Task HandleAsync(RequestDelegate next,
      HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
    {
        var endPoint = context.GetEndpoint();

        var controllerActionDescriptor = (ControllerActionDescriptor)endPoint.Metadata
          .ToList().FirstOrDefault(d => d is ControllerActionDescriptor);

        var controllerName = controllerActionDescriptor.ControllerName;

        var actionName = controllerActionDescriptor.ActionName;

        if (!context.User.Identity.IsAuthenticated)
        {
            context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            await context.Response.WriteAsync("{\"data\":{\"succeeded\":false,\"code\":401,\"message\":\"登录已过期,请重新登录\"}}");
            return;
        }
        else if (!await HandleRequirementEvaluateAsync(context.User, controllerName, actionName))
        {
            context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
            await context.Response.WriteAsync("{\"data\":{\"succeeded\":false,\"code\":403,\"message\":\"您暂无足够的权限执行该操作\"}}");
            return;
        }
        await next(context);
    }
}

自从.NET 5有了IAuthorizationMiddlewareResultHandler授权中间件接口,一切又是那么得心应手!

到此这篇关于.NET Core授权失败如何自定义响应信息的文章就介绍到这了,更多相关.NET Core自定义响应信息内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • .NET Core2.1如何获取自定义配置文件信息详解

    前言 .net core来势已不可阻挡.既然挡不了,那我们就顺应它.了解它并学习它.今天我们就来看看和之前.net版本的配置文件读取方式有何异同,这里不在赘述.NET Core 基础知识.下面话不多说了,来一起看看详细的介绍吧 实现 注:需要NuGet引入:Microsoft.Extensions.Options.ConfigurationExtensions ①我们再配置文件appsettings.json中 新增自定义API Json如下: { "Logging": { "

  • ASP.NET Core自定义中间件如何读取Request.Body与Response.Body的内容详解

    背景# 最近在徒手造轮子,编写一个ASP.NET Core的日志监控器,其中用到了自定义中间件读取Request.Body和Response.Body的内容,但是编写过程,并不像想象中的一帆风顺,ASP.NET Core针对Request.Body和Response.Body的几个特殊设计,导致了完成以上功能需要绕一些弯路. 原始代码# 为了读取Request.Body和Response.Body的内容,我的实现思路如下: 创建一个LoggerMiddleware的中间件,将它放置在项目中间件管

  • ASP.NET Core自定义本地化教程之从文本文件读取本地化字符串

    前言 本文先简要介绍在ASP.NET Core 2.0里实施全球化和本地化,默认的本地化从资源文件(resx)里读取本地化字符串.本文然后提供一个简单示例,说明如何自定义本地化,以便从文本文件读取本地化字符串. 实施全球化和本地化 国际化涉及全球化和本地化. 全球化是设计支持不同区域性的应用程序的过程. 全球化添加了对一组有关特定地理区域的已定义语言脚本的输入.显示和输出支持. 本地化是将已经针对可本地化性进行处理的全球化应用调整为特定的区域性/区域设置的过程. 有关详细信息,请参阅本文档邻近末

  • 详解.Net Core 权限验证与授权(AuthorizeFilter、ActionFilterAttribute)

    在.Net Core 中使用AuthorizeFilter或者ActionFilterAttribute来实现登录权限验证和授权 一.AuthorizeFilter 新建授权类AllowAnonymous继承AuthorizeFilter,IAllowAnonymousFilter public class AllowAnonymous : AuthorizeFilter, IAllowAnonymousFilter { } 新建拦截类继承AuthorizeFilter public class

  • asp.net core2.2多用户验证与授权示例详解

    前言 asp.net core2.2 用户验证 和授权有很详细和特贴心的介绍,我感兴趣的主要是这两篇: cookie身份验证 基于角色的授权 我的项目有两类用户: 微信公众号用户,用户名为公众号的openid 企业微信的用户,用户名为企业微信的userid 每类用户中部分人员具有"Admin"角色 因为企业微信的用户有可能同时是微信公众号用户,即一个人两个名,所以需要多用户验证和授权.咱用代码说话最简洁,如下所示: public class DemoController : Contr

  • .Net Core官方JWT授权验证的全过程

    什么是JWT? JSON Web令牌(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间安全地传输信息作为JSON对象.由于此信息是经过数字签名的,因此可以被验证和信任.可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对对JWT进行签名. 尽管可以对JWT进行加密以提供双方之间的保密性,但我们将重点关注已签名的令牌.签名的令牌可以验证其中包含的声明的完整性,而加密的令牌则将这些声明隐藏在其他方的面前.当使用公钥/私钥对对令牌进行签名时,

  • ASP.NET Core使用自定义验证属性控制访问权限详解

    前言 大家都知道在应用中,有时我们需要对访问的客户端进行有效性验证,只有提供有效凭证(AccessToken)的终端应用能访问我们的受控站点(如WebAPI站点),此时我们可以通过验证属性的方法来解决. 本文将详细介绍ASP.NET Core使用自定义验证属性控制访问权限的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧 方法如下 一.public class Startup的配置: //启用跨域访问(不同端口也是跨域) services.AddCors(options

  • .NET Core授权失败自定义响应信息的操作方法

    前言 在.NET 5之前,当授权失败即403时无法很友好的自定义错误信息,以致于比如利用Vue获取到的是空响应,不能很好的处理实际业务,同时涉及到权限粒度控制到控制器.Action,也不能很好的获取对应路由信息.本文我们来看看在.NET 5中为何要出现针对授权失败的中间件接口?它是如何一步步衍生出来的呢?以及对于授权失败根据实际需要如何自定义响应错误,以及如何获取对应路由信息等等 授权失败自定义响应信息 如下是在.NET 5之前,对于授权处理,我们大多实现自定义的AuthorizationHan

  • ASP.NET Core AutoWrapper 自定义响应输出实现

    前言 AutoWrapper是一个简单可自定义全局异常处理程序和ASP.NET Core API响应的包装.他使用ASP.NET Core middleware拦截传入的HTTP请求,并将最后的结果使用统一的格式来自动包装起来.目的主要是让我们更多的关注业务特定的代码要求,并让包装器自动处理HTTP响应.这可以在构建API时加快开发时间,同时为HTTP响应试试我们统一的标准. 安装 AutoWrapper.Core从NuGet或通过CLI下载并安装 PM> Install-Package Aut

  • Asp.net Core中实现自定义身份认证的示例代码

    Asp.Net Core中虽然集成了许多常用的身份认证,但很多时候,我们还是需要实现自己的身份认证接口,本文这里就简单的介绍下如何实现自定义身份认证接口. 首先写一个简单的接口. [Authorize] [HttpGet] public object Foo() { return DateTime.Now.ToString(); } 由于有Authorize标记,访问函数体前会判断用户是否通过认证,由于这里没有通过认证,会的得到一个500错误. 自定义认证处理类: 实现一个IAuthentica

  • Spring Cloud Gateway 如何修改HTTP响应信息

    Gateway 修改HTTP响应信息 实践Spring Cloud的过程中,使用Gateway作为路由组件,并且基于Gateway实现权限的验证.拦截.过滤,对于下游微服务的响应结果,我们总会有需要修改以统一数据格式,或者修改过滤用户没有权限看到的数据信息,这时候就需要有一个能够修改响应体的Filter. Spring Cloud Gateway 版本为2.1.0 在当前版本,ModifyRequestBodyGatewayFilterFactory是官方提供的修改响应体的参考类,This fi

  • Laravel+Dingo/Api 自定义响应的实现

    在最近的开发开发项目中,我使用了Dingo/Api这个第三方Api库. Dingo是个很强大的Api库, 但在开发的过程中,需要自定义响应字段. 刚开始使用Ding/Api时,返回如下: { "message": "422 Unprocessable Entity", "errors": { "mobile": [ "手机号格式不正确" ] }, "status_code": 422 }

  • IdentityServer4 QuckStart 授权与自定义Claims的问题

    最近在折腾IdentityServer4,为了简单,直接使用了官方给的QuickStart示例项目作为基础进行搭建.有一说一,为了保护一个API,感觉花费的时间比写一个API还要多. 本文基于ASP.NET CORE 3.1, IdentityServer4 3.1.3.代码皆为关键代码,贴全了太多了. 好不容易跑起来了,最终的任务要落实到授权的工作上来.在API中使用Authorize用来限制用户的访问. [Route("api/[controller]")] [Authorize(

  • SpringSecurityOAuth2 如何自定义token信息

    GitHub地址 码云地址 OAuth2默认的token返回最多只携带了5个参数(client_credentials模式只有4个 没有refresh_token) 下面是一个返回示例: { "access_token": "1e93bc23-32c8-428f-a126-8206265e17b2", "token_type": "bearer", "refresh_token": "0f083e

  • 使用BindingResult 自定义错误信息

    目录 BindingResult 自定义错误信息 前提概要 基础框架 配置文件和Java代码的修改 在Controller方法中指定需要进行校验 进行自定义校验 在JSP页面上显示校验错误信息 BindingResult错误返回显示失败 BindingResult 自定义错误信息 前提概要 在Spring MVC和FreeMarker整合的项目中,采用JSR-303验证框架,通过注解的方式进行数据验证 基础框架 MVC:Spring MVC 3 视图:FreeMarker 验证:Hibernat

  • .Net Core授权认证方案JWT(JSON Web Token)初探

    一.前言 现在越来越多的项目或多或少会用到JWT,为什么会出现使用JWT这样的场景的呢? 假设现在有一个APP,后台是分布式系统.APP的首页模块部署在上海机房的服务器上,子页面模块部署在深圳机房的服务器上.此时你从首页登录了该APP,然后跳转到子页面模块.session在两个机房之间不能同步,用户是否需要重新登录? 传统的方式(cookie+session)需要重新登录,用户体验不好.session共享(在多台物理机之间传输和复制session)方式对网络IO的压力大,延迟太长,用户体验也不好

  • 在ASP.NET Core中显示自定义的错误页面

    前言 相信每位程序员们应该都知道在 ASP.NET Core 中,默认情况下当发生500或404错误时,只返回http状态码,不返回任何内容,页面一片空白. 如果在 Startup.cs 的 Configure() 中加上 app.UseStatusCodePages(); ,500错误时依然是一片空白(不知为何对500错误不起作用),404错误时有所改观,页面会显示下面的文字: Status Code: 404; Not Found 如果我们想实现不管500还是404错误都显示自己定制的友好错

随机推荐