aspnet core 2.1中使用jwt从原理到精通二

在aspnet core中,自定义jwt管道验证

有了上一节的内容作为基础,那这点也是非常容易的,关键点在中间件,只是把上一级在测试类中的自定义验证放到中间件中来即可,

不过需要注意:中间件 的位置很重要,只有它后面的管道才会收到影响;

那我们先建一个自定义中间件类:(中间件的详细内容这里就不讲了,大家可以参考官网和其他博文)

/// <summary>

    /// 自定义授权中间件

    /// </summary>

    public class JwtCustomerAuthorizeMiddleware

    {

        private readonly RequestDelegate next;


        public JwtCustomerAuthorizeMiddleware(RequestDelegate next, string secret, List<string> anonymousPathList)

        {

            #region   设置自定义jwt 的秘钥

            if(!string.IsNullOrEmpty(secret))

            {

                TokenContext.securityKey = secret;

            }

            #endregion

            this.next = next;

            UserContext.AllowAnonymousPathList.AddRange(anonymousPathList);

        }


        public async Task Invoke(HttpContext context, UserContext userContext,IOptions<JwtOption> optionContainer)

        {

            if (userContext.IsAllowAnonymous(context.Request.Path))

            {

                await next(context);

                return;

            }


            var option = optionContainer.Value;


            #region 身份验证,并设置用户Ruser值

 

            var result = context.Request.Headers.TryGetValue("Authorization", out StringValues authStr);

            if (!result || string.IsNullOrEmpty(authStr.ToString()))

            {

                throw new UnauthorizedAccessException("未授权");

            }

            result = TokenContext.Validate(authStr.ToString().Substring("Bearer ".Length).Trim(), payLoad =>

            {

                var success = true;

                //可以添加一些自定义验证,用法参照测试用例

                //验证是否包含aud 并等于 roberAudience

                success = success && payLoad["aud"]?.ToString() == option.Audience;

                if (success)

                {

                    //设置Ruse值,把user信息放在payLoad中,(在获取jwt的时候把当前用户存放在payLoad的ruser键中)

                    //如果用户信息比较多,建议放在缓存中,payLoad中存放缓存的Key值

                    userContext.TryInit(payLoad["ruser"]?.ToString());

                }

                return success;

            });

            if (!result)

            {

                throw new UnauthorizedAccessException("未授权");

            }


            #endregion

            #region 权限验证

            if (!userContext.Authorize(context.Request.Path))

            {

                throw new UnauthorizedAccessException("未授权");

            }

            #endregion


            await next(context);

        }

    }

上面这个中间件中有个UserContext上线文,这个类主要管理当前用户信息和权限,其他信息暂时不管;我们先看一下这个中间件的验证流程如何:

该中间件主要是针对访问的路径进行验证,当然你也可以针对其他信息进行验证,比如(控制器名称,动作名称,等)

  1. 检查当前url是否可以匿名访问,如果可以就直接通过,不做验证了;如果不是可以匿名访问的路径,那就继续

  2. 获取当前http头部携带的jwt(存放在头部的 Authorization中);

  3. 使用上一节的讲的TokenContext做必须的验证和自定义复杂验证;

  4. 获取当前访问用户信息,我们把用户的基本信息放在payLoad["ruser"]中,请看代码如何操作

  5. 到这里为止,都是做的身份验证,表明你是一个有身份的的人;接下来是做权限验证,你是一个有身份的人,并不代表你是一个随便到处访问的人;你能访问哪些url或者action,就要得到权限验证的认可

  6. 我们把权限验证放到 userContext.Authorize方法中(这里怎么操作,这里就不深入讲解,基本原理是从数据库或者缓存中获取当前用户对应的权限列表,也就是url列表,进行对比);

自定义中间件使用jwt验证就这些内容,是不是感觉很清晰,很简单,有木有;

中间已经完成了,那接下来我们来使用它,我们再startup中的Configure方法中添加如下代码

app.UseMiddleware<JwtCustomerAuthorizeMiddleware>(Configuration["JwtOption:SecurityKey"], new List<string>() { "/api/values/getjwt","/" });

当然上面可匿名访问的url也可以定义在appsetting.json文件中,可以自行尝试

如何通过自定义策略形式实现自定义jwt验证

创建自定义策略的详细介绍可以参考官网,这里就不详细介绍,

首先我们上代码,创建自定义策略非常重要的两个类,如下:

public class CommonAuthorizeHandler : AuthorizationHandler<CommonAuthorize>

    {

        /// <summary>

        /// 常用自定义验证策略,模仿自定义中间件JwtCustomerauthorizeMiddleware的验证范围

        /// </summary>

        /// <param name="context"></param>

        /// <param name="requirement"></param>

        /// <returns></returns>

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CommonAuthorize requirement)

        {

            var httpContext = (context.Resource as AuthorizationFilterContext).HttpContext;

            var userContext = httpContext.RequestServices.GetService(typeof(UserContext)) as UserContext;


            var jwtOption = (httpContext.RequestServices.GetService(typeof(IOptions<JwtOption>)) as IOptions<JwtOption>).Value;


            #region 身份验证,并设置用户Ruser值


            var result = httpContext.Request.Headers.TryGetValue("Authorization", out StringValues authStr);

            if (!result || string.IsNullOrEmpty(authStr.ToString()))

            {

                return Task.CompletedTask;

            }

            result = TokenContext.Validate(authStr.ToString().Substring("Bearer ".Length).Trim(), payLoad =>

            {

                var success = true;

                //可以添加一些自定义验证,用法参照测试用例

                //验证是否包含aud 并等于 roberAudience

                success = success && payLoad["aud"]?.ToString() == jwtOption.Audience;

                if (success)

                {

                    //设置Ruse值,把user信息放在payLoad中,(在获取jwt的时候把当前用户存放在payLoad的ruser键中)

                    //如果用户信息比较多,建议放在缓存中,payLoad中存放缓存的Key值

                    userContext.TryInit(payLoad["ruser"]?.ToString());

                }

                return success;

            });

            if (!result)

            {

                return Task.CompletedTask;

            }


            #endregion

            #region 权限验证

            if (!userContext.Authorize(httpContext.Request.Path))

            {

                return Task.CompletedTask;

            }

            #endregion


            context.Succeed(requirement);

            return Task.CompletedTask;

        }

    }

    public class CommonAuthorize: IAuthorizationRequirement

    {


    }

其中两个重要的类是哪两个呢?他们的作用又是什么呢?

  1. CommonAuthorize: IAuthorizationRequirement,至于取什么名字,自己定义,但必须继承IAuthorizationRequirement,这类主要是承载一些初始化值,让后传递到Handler中去,给验证做逻辑运算提供一些可靠的信息;我这里是空的;自己根据自身情况自己定义适当的属性作为初始数据的承载容器;
  2. CommonAuthorizeHandler : AuthorizationHandler<CommonAuthorize>这个是重点,承载了验证的逻辑运算
    需要重写override Task HandleRequirementAsync方法,所有的逻辑都在该方法中,他的主要逻辑和上面的自定义中间件很相似,只少了上面的第一步;验证流程如下:
    1. 获取当前http头部携带的jwt(存放在头部的 Authorization中);

    2. 使用上一节的讲的TokenContext做必须的验证和自定义复杂验证;

    3. 获取当前访问用户信息,我们把用户的基本信息放在payLoad["ruser"中,请看代码如何操作

    4. 到这里为止,都是做的身份验证,表明你是一个有身份的的人;接下来是做权限验证,你是一个有身份的人,并不代表你是一个随便到处访问的人;你能访问哪些url或者action,就要得到权限验证的认可

    5. 我们把权限验证放到 userContext.Authorize方法中(这里怎么操作,这里就不深入讲解,基本原理是从数据库或者缓存中获取当前用户对应的权限列表,也就是url列表,进行对比);

      context.Succeed(requirement);是验证成功,如果没有这个,就默认验证失败

      因为UserContext把负责了权限验证,所以不会把流程搞得感觉很乱,并且可以重用,至于用那种形式验证也很容易切换

  3. 是不是很简单,和自定义管道验证的的代码几乎一模一样,

如何使用自定义定义策略呢?

  1. 在startup类中的ConfigureServices中加入如下代码:

640?wx_fmt=png

  1. 以上代码主要分3个部分
    1、添加上面自定义的策略,并取名;
    2、设置秘钥,这个秘钥就是上一节中生成jwt的秘钥,必须要要一样,否则是签名不正确
    3、注入上面建立的一个重要类CommonAuthorizeHandler,如上面代码

  2. 在startup类中的Configure中添加 app.UseAuthentication();

  3. 在需要验证的Controller或者Action中加上[Authorize(Policy = "common")]属性,看下图:
    640?wx_fmt=png

    到此为止你就可以使用自定义策略的验证了;

 

使用管道和自定义策略两种形式进行验证有什么区别呢?

从效果上看都是一样的,稍微有点区别

  1. 使用管道的方式,感觉方便点,清晰点

  2. 使用自定义策略的方式,效率稍微高一点,毕竟不是所有的请求都会进行是否可以匿名访问运算和建立管道的消耗,只有加入Authorize属性的Controller和Action的才会进入;当然这点损耗可以忽略不计,看自己的喜好;

至于你喜欢那种,就使用哪种吧,性能可以忽略不计;

不管使用哪种方式使用jwt作为身份和权限验证是不是很简单,关键这里也把权限验证的逻辑抽出来了,这样代码就更清晰明了了;

至于Authorize的属性形式,还有很多其他的策略,比如用户、申明,角色等,可查看官网https://docs.microsoft.com/zh-cn/aspnet/core/security/authorization/?view=aspnetcore-2.0

下一章将讲解 用户,申明 ,角色的验证,并这些怎么在自定义的验证中实现,以便大家对他有个清晰的对比

相关文章:

  • aspnet core 2.1中使用jwt从原理到精通一

  • IdentityServer4之JWT签名(RSA加密证书)及验签

  • IdentityServer4实战 - 谈谈 JWT Token 的安全策略

  • 如何简单的在 ASP.NET Core 中集成 JWT 认证?

原文地址: https://www.cnblogs.com/lechengbo/p/9861501.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/319206.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CentOS开发ASP.NET Core入门教程

因为之前一直没怎么玩过CentOS&#xff0c;大多数时间都是使用Win10进行开发&#xff0c;然后程序都部署在Window Server2008或者Window Server2012上&#xff01;因此想尝试下Linux系统。最后经过选型选了比较流行的CentOS系统。正好&#xff0c;今晚要加班&#xff0c;所以在…

工厂参观记:.NET Core 中 HttpClientFactory 如何解决 HttpClient 臭名昭著的问题

在 .NET Framework 与 .NET Core 中 HttpClient 有个臭名昭著的问题&#xff0c;HttpClient 实现了 IDispose 接口&#xff0c;但当你 Dispose 它时&#xff0c;它不会立即关闭所使用的 tcp 连接&#xff0c;而是将 tcp 连接置为 TIME_WAIT 状态&#xff0c;240秒&#xff08;4…

ASP.NET Core2读写InfluxDB时序数据库

在我们很多应用中会遇到有一种基于一系列时间的数据需要处理&#xff0c;通过时间的顺序可以将这些数据点连成线&#xff0c;再通过数据统计后可以做成多纬度的报表&#xff0c;也可通过机器学习来实现数据的预测告警。而时序数据库就是用于存放管理这种有着时间顺序数据的&…

Nature 新研究发布,GPT 驱动的机器人化学家能够自行设计和进行实验,这对科研意味着什么?

文章目录 前言揭秘Coscientist不到四分钟&#xff0c;设计并改进了程序能力越大&#xff0c;责任越大 前言 有消息称&#xff0c;AI 大模型 “化学家” 登 Nature 能够自制阿司匹林、对乙酰氨基酚、布洛芬&#xff0c;甚至连复杂的钯催化交叉偶联反应&#xff0c;也能完成。 …

SmartCode 常见问题

SmartCode 能干什么&#xff1f;SmartCode IDataSource -> IBuildTask -> IOutput > Build EverythingSmartCode的执行流是 数据源->构建任务->输出&#xff0c;也就是说应用场景非常广泛。从DB读取数据结构&#xff0c;最终生成整个解决方案代码生成器&#x…

全面支持开源,微软加速 Visual Studio 和 Azure DevOps 云升级

在 2018 微软技术暨生态大会&#xff08;Microsoft Tech Summit&#xff09;上&#xff0c;微软宣布围绕 Visual Studio 和 Visual Studio Code 开发平台提供一系列新功能与服务&#xff0c;并对 Azure DevOps 研发云进行整合升级&#xff0c;通过 Visual Studio 开发平台与微软…

HttpClient参观记:.net core 2.2 对HttpClient到底做了什么?

.net core 于 10月17日发布了 ASP.NET Core 2.2.0 -preview3&#xff0c;在这个版本中&#xff0c;我看到了一个很让我惊喜的新特性&#xff1a;HTTP Client Performance Improvements &#xff0c;而且在Linux上性能提升了60% !之前就一直苦于 HttpClient 的糟糕特性&#xff…

后缀数组(讲解)

子串&#xff1a;从原串中选取连续的一段&#xff0c;即子串 空串也是子串 后缀&#xff1a;suf(k)为s(k…n)构成的子串 任何子串都是某个后缀的前缀 最长公共前缀 lcp(suf(i),suf(j)) 问题&#xff1a; 将所有后缀suf(1),suf(2),suf(N)按照字典序从小到大排序 暴力sort N2 …

2018 上海.NET职位围观报告

我一直说我是夏眠动物&#xff0c;如今已经11月份了&#xff0c;差不多也该活过来了&#xff0c;所以我决定写篇文章给各位.NET的支持者们和公司打打气&#xff0c;也算是为社区做点贡献吧。我最近主要干了两件事&#xff1a;让NPOI支持.NET Core&#xff0c;现已发布2.4版本。…

老张 .NetCore与Vue 框架学习

缘起作为一个.Net攻城狮已经4年有余了&#xff0c;一直不温不火&#xff0c;正好近来项目不是很忙&#xff0c;闲得无聊&#xff0c;搞一搞新技术&#xff0c;一方面是打发无聊的时间&#xff0c;一方面也是督促自己该学习辣&#xff01;身边的大神都转行的转行&#xff0c;加薪…

2018年10月28日宁波dotnet社区活动回顾及下次活动预告

离上次活动&#xff0c;有半年了&#xff0c;汗。之后尽量保证每月一次&#xff0c;以组织为主&#xff0c;多邀请嘉宾来分享。本次活动不足之处人手不足&#xff1a;由于活动组织事项受限于人手&#xff08;目前就我一个&#xff0c;这次活动前后我又应邀给大红鹰学院应届生介…

[JSOI2007]字符加密

题目描述 喜欢钻研问题的JS 同学&#xff0c;最近又迷上了对加密方法的思考。一天&#xff0c;他突然想出了一种他认为是终极的加密办法&#xff1a;把需要加密的信息排成一圈&#xff0c;显然&#xff0c;它们有很多种不同的读法。 例如‘JSOI07’&#xff0c;可以读作&…

BotSharp v0.2 发布, 支持微信智能回复

BotSharp v0.2 主要是针对微信的消息平台做整合&#xff0c;让.NET开发者可以轻松的搭建基于NLU自然语言理解的智能回复功能&#xff0c;BotSharp.Channel.Weixin模块负责和微信的公众号平台对接&#xff0c;接收消息通知&#xff0c;并能消息产生智能回复&#xff0c;回复的内…

P2852 [USACO06DEC]Milk Patterns G

题目描述 Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can’t predict the quality of milk from one day to the next, there are some regular patterns in th…

c# 弹性和瞬态故障处理库Polly 学习

关于PollyPolly是一个基于.NET的弹性及瞬态故障处理库,允许开发人员以顺畅及线程安全的方式执行重试(Retry)、断路(Circuit Breaker)、超时(Timeout)、隔离(Bulkhead Isolation)和回退策略(Fallback ).Polly适用于 .NET 4.0, .NET 4.5 和.NET Standard 1.1。以上是官方文档对po…

TechEmpower最新一轮的性能测试出炉,ASP.NET Core依旧表现不俗

TechEmpower在10月30发布最新一轮&#xff08;Round 17&#xff09;针对“Web Framework Benchmarks”的性能测试报告&#xff0c;ASP.NET Core依旧表现不俗&#xff0c;在一些指标上甚至是碾压其他主流Web框架。为此我们做了一个简单的统计&#xff0c;看看ASP.NET Core和其他…

国内开源社区巨作AspectCore-Framework入门

前些天和张队(善友),lemon(浩洋),斌哥(项斌)等MVP大咖一块儿吃饭,大家聊到了lemon名下的AOP这个项目,我这小白听得一脸懵逼,后面回来做了一下功课,查了下资料,在lemon的Github上把这个项目学习了一下,收获颇丰,让我这个没有接触过AOP的Coder叹为观止,陷入了对lemon的深深崇拜,在…

HarmonyOs4.0基础(一)

目录 一、HarmonyOs系统定义 1.1系统的技术特性(三大特征) 1.1.1、硬件互助、资源共享 1.1.2、一次开发、多端部署(面向开发者) 1.1.3、统一OS&#xff0c;弹性部署(支持多种API&#xff1a;ArkTs、JS、C/C、Java) 1.2、系统的技术架构 二、Harmony OS项目搭建 2.1、(D…

swagger文档转换为WebApiClient声明式代码

1 swagger简介Swagger是一个规范且完整的框架&#xff0c;提供描述、生产、消费和可视化RESTful Web Service。其核心是使用json来规范描述RESTful接口&#xff0c;另外有提供UI来查看接口说明&#xff0c;并有一套生成不同语言的客户端调用代码生成器。1.1 对Api提供者自顶向下…

Musical Theme pku1743 (后缀数组)

Musical Theme(后缀数组) 题意&#xff1a; n个数&#xff0c;选取一段子序列&#xff0c;满足以下条件&#xff1a; 1.长度至少为5 2.在数列中其他位置出现过(允许转置) 3.与其他位置出现的不重叠 转置&#xff1a;将恒定的正或负值添加到子序列上 例如&#xff1a; n个数为…