ASP.NET Core 基于JWT的认证(二) 置顶!

ASP.NET Core 基于JWT的认证(二)

上一节我们对 Jwt 的一些基础知识进行了一个简单的介绍,这一节我们将详细的讲解,本次我们将详细的介绍一下 Jwt.Net Core 上的实际运用。

环境

  • .Net Core 2.2

  • Visual Studio 2017

  • ASP.NET Core WebAPI2

在上一篇文章中,我们详细的介绍了JWT的知识,这一次,我们将进行一次实战的训练,这一块将会有三个部分组成。分别是:

1.如何使用微软官方提供的库实现jwt

2.如何自定义一个Jwt认证类

3.使用非关系型数据库Redisjwt信息的更新和替换

当然,我在后期的文章中也会讲解如何使用IdentityServer4去进行我们的权限控制。

在本文中,你将会学到如何使用微软官方提供的库进行Jwt的签发、验证以及权限控制。我们使用的WebApi作为演示程序。

配置信息的存储

通常来说,我们会把数据库等等一系列的配置放在我们的appsettings.json中,我们也尝试着将我们的jwt私钥等存在其中。


<div><span style="color: #bbbbbb;"></span><span style="color: #98c379;">"JwtSettings"</span><span style="color: #bbbbbb;">: {</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #e06c75;">"Issuer"</span><span style="color: #bbbbbb;">:</span> <span style="color: #98c379;">"admin"</span><span style="color: #bbbbbb;">,</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #e06c75;">"Audience"</span><span style="color: #bbbbbb;">:</span> <span style="color: #98c379;">"user"</span><span style="color: #bbbbbb;">,</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #e06c75;">"SecretKey"</span><span style="color: #bbbbbb;">:</span> <span style="color: #98c379;">"ahfuawivb754huab21n5n1"</span></div>

<div><span style="color: #bbbbbb;">}</span></div>

<div><span style="color: #bbbbbb;">```

当然你也可以把更多的配置放进去。

然后我们用依赖注入的方法,将配置文件注入到我们的类对象中。我们创建一个JwtSetting类,并且在服务中进行注入。

类对象

``` C#</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">public</span> <span style="color: #bbbbbb;"></span> <span style="color: #c678dd;">class</span> <span style="color: #bbbbbb;"></span> <span style="color: #e5c07b;">JwtSettings</span></div>

<div><span style="color: #bbbbbb;">{</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #5c6370;font-style: italic;">///</span> <span style="color: #abb2bf;font-style: italic;"><</span><span style="color: #e06c75;font-style: italic;">summary</span><span style="color: #abb2bf;font-style: italic;">></span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #5c6370;font-style: italic;">/// 证书颁发者</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #5c6370;font-style: italic;">///</span> <span style="color: #abb2bf;font-style: italic;"></</span><span style="color: #e06c75;font-style: italic;">summary</span><span style="color: #abb2bf;font-style: italic;">></span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">public</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">string</span> <span style="color: #61afef;">Issuer</span> <span style="color: #bbbbbb;">{</span> <span style="color: #c678dd;">get</span><span style="color: #bbbbbb;">;</span> <span style="color: #c678dd;">set</span><span style="color: #bbbbbb;">; }</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #5c6370;font-style: italic;">///</span> <span style="color: #abb2bf;font-style: italic;"><</span><span style="color: #e06c75;font-style: italic;">summary</span><span style="color: #abb2bf;font-style: italic;">></span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #5c6370;font-style: italic;">/// 允许使用的角色</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #5c6370;font-style: italic;">///</span> <span style="color: #abb2bf;font-style: italic;"></</span><span style="color: #e06c75;font-style: italic;">summary</span><span style="color: #abb2bf;font-style: italic;">></span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">public</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">string</span> <span style="color: #61afef;">Audience</span> <span style="color: #bbbbbb;">{</span> <span style="color: #c678dd;">get</span><span style="color: #bbbbbb;">;</span> <span style="color: #c678dd;">set</span><span style="color: #bbbbbb;">; }</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #5c6370;font-style: italic;">///</span> <span style="color: #abb2bf;font-style: italic;"><</span><span style="color: #e06c75;font-style: italic;">summary</span><span style="color: #abb2bf;font-style: italic;">></span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #5c6370;font-style: italic;">/// 加密字符串</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #5c6370;font-style: italic;">///</span> <span style="color: #abb2bf;font-style: italic;"></</span><span style="color: #e06c75;font-style: italic;">summary</span><span style="color: #abb2bf;font-style: italic;">></span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">public</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">string</span> <span style="color: #61afef;">SecretKey</span> <span style="color: #bbbbbb;">{</span> <span style="color: #c678dd;">get</span><span style="color: #bbbbbb;">;</span> <span style="color: #c678dd;">set</span><span style="color: #bbbbbb;">; }</span></div>

<div><span style="color: #bbbbbb;">}</span></div>

<div><span style="color: #bbbbbb;">```

注入

``` C#</span></div>

<div><span style="color: #abb2bf;">services</span><span style="color: #bbbbbb;">.</span><span style="color: #61afef;">Configure</span><span style="color: #bbbbbb;"><JwtSettings></span><span style="color: #bbbbbb;">(</span><span style="color: #abb2bf;">Configuration</span><span style="color: #bbbbbb;">.</span><span style="color: #61afef;">GetSection</span><span style="color: #bbbbbb;">(</span><span style="color: #98c379;">"JwtSettings"</span><span style="color: #bbbbbb;">));</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #bbbbbb;">JwtSettings</span> <span style="color: #bbbbbb;">setting</span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #c678dd;">new</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">JwtSettings</span><span style="color: #bbbbbb;">();</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #abb2bf;">Configuration</span><span style="color: #bbbbbb;">.</span><span style="color: #61afef;">Bind</span><span style="color: #bbbbbb;">(</span><span style="color: #98c379;">"JwtSettings"</span><span style="color: #bbbbbb;">,</span> <span style="color: #abb2bf;">setting</span><span style="color: #bbbbbb;">);</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #abb2bf;">JwtHelper</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">Settings</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">setting</span><span style="color: #bbbbbb;">;</span></div>

<div><span style="color: #bbbbbb;">```

想必这里的代码大家肯定是看的轻车熟路了,非常的简单。

接下来我们对Jwt的签发制作一个*JwtHelper*类。

### Jwt的签发

这一块,你可以上网去查看[权限模型]("http://www.cnblogs.com/savorboard/p/aspnetcore-identity.html")的一些介绍。

这里我简要的做一个介绍:

*Claim*是什么呢,他就是一个用于描述一个具体的实体对象的一些描述性的字段。

*ClaimsIdentity*就是用于指明Claim中所存储的内容的合集,比如我们的身份证,年龄、性别、身份证号码等就组成了我们的身份证。

*ClaimsPrincipal*我们称为“证件当事人”,也就是我们之前声明的东西的一个合计,类似,比如说你可能有驾照、身份证、医保卡等等,而所持有这些的人就叫做*ClaimsPrincipal*

一些代码是一个普通的结构,大家可以按照这种模板进行修改模型,从而创建自己的jwt结构

代码:

``` C#</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">public</span> <span style="color: #bbbbbb;"></span> <span style="color: #c678dd;">class</span> <span style="color: #bbbbbb;"></span> <span style="color: #e5c07b;">JwtHelper</span></div>

<div><span style="color: #bbbbbb;">{</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">private</span> <span style="color: #bbbbbb;"></span> <span style="color: #c678dd;">static</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">JwtSettings</span> <span style="color: #bbbbbb;"></span> <span style="color: #e06c75;">settings</span><span style="color: #bbbbbb;">;</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">public</span> <span style="color: #bbbbbb;"></span> <span style="color: #c678dd;">static</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">JwtSettings</span> <span style="color: #61afef;">Settings</span> <span style="color: #bbbbbb;">{</span> <span style="color: #c678dd;">set</span> <span style="color: #bbbbbb;">{</span> <span style="color: #abb2bf;">settings</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">value</span><span style="color: #bbbbbb;">; } }</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">public</span> <span style="color: #bbbbbb;"></span> <span style="color: #c678dd;">static</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">string</span> <span style="color: #61afef;">create_Token</span><span style="color: #bbbbbb;">(</span><span style="color: #bbbbbb;">TokenPayload</span> <span style="color: #bbbbbb;">user)</span></div>

<div><span style="color: #bbbbbb;">{</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #5c6370;font-style: italic;">//这里就是声明我们的claim</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">var</span> <span style="color: #bbbbbb;">claims</span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #c678dd;">new</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">Claim[]</span> <span style="color: #bbbbbb;">{</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">new</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">Claim</span><span style="color: #bbbbbb;">(</span><span style="color: #abb2bf;">ClaimTypes</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">Name</span><span style="color: #bbbbbb;">,</span> <span style="color: #abb2bf;">user</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">Name</span><span style="color: #bbbbbb;">),</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">new</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">Claim</span><span style="color: #bbbbbb;">(</span><span style="color: #abb2bf;">ClaimTypes</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">Role</span><span style="color: #bbbbbb;">,</span> <span style="color: #abb2bf;">user</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">Role</span><span style="color: #bbbbbb;">),</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">new</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">Claim</span><span style="color: #bbbbbb;">(</span><span style="color: #abb2bf;">ClaimTypes</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">Sid</span><span style="color: #bbbbbb;">,</span><span style="color: #abb2bf;">user</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">Sid</span><span style="color: #bbbbbb;">.</span><span style="color: #61afef;">ToString</span><span style="color: #bbbbbb;">())</span></div>

<div><span style="color: #bbbbbb;">};</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">var</span> <span style="color: #bbbbbb;">key</span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #c678dd;">new</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">SymmetricSecurityKey</span><span style="color: #bbbbbb;">(</span><span style="color: #abb2bf;">Encoding</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">UTF8</span><span style="color: #bbbbbb;">.</span><span style="color: #61afef;">GetBytes</span><span style="color: #bbbbbb;">(</span><span style="color: #abb2bf;">settings</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">SecretKey</span><span style="color: #bbbbbb;">));</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">var</span> <span style="color: #bbbbbb;">creds</span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #c678dd;">new</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">SigningCredentials</span><span style="color: #bbbbbb;">(</span><span style="color: #abb2bf;">key</span><span style="color: #bbbbbb;">,</span> <span style="color: #abb2bf;">SecurityAlgorithms</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">HmacSha256</span><span style="color: #bbbbbb;">);</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">var</span> <span style="color: #bbbbbb;">token</span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #c678dd;">new</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">JwtSecurityToken</span><span style="color: #bbbbbb;">(</span></div>

<div><span style="color: #bbbbbb;">issuer:</span> <span style="color: #abb2bf;">settings</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">Issuer</span><span style="color: #bbbbbb;">,</span></div>

<div><span style="color: #bbbbbb;">audience:</span> <span style="color: #abb2bf;">settings</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">Audience</span><span style="color: #bbbbbb;">,</span></div>

<div><span style="color: #bbbbbb;">claims:</span> <span style="color: #abb2bf;">claims</span><span style="color: #bbbbbb;">,</span></div>

<div><span style="color: #bbbbbb;">expires:</span> <span style="color: #abb2bf;">DateTime</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">Now</span><span style="color: #bbbbbb;">.</span><span style="color: #61afef;">AddDays</span><span style="color: #bbbbbb;">(</span><span style="color: #d19a66;">1</span><span style="color: #bbbbbb;">),</span></div>

<div><span style="color: #bbbbbb;">signingCredentials:</span> <span style="color: #abb2bf;">creds</span><span style="color: #bbbbbb;">);</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">var</span> <span style="color: #bbbbbb;">Token</span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #c678dd;">new</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">JwtSecurityTokenHandler</span><span style="color: #bbbbbb;">().</span><span style="color: #61afef;">WriteToken</span><span style="color: #bbbbbb;">(</span><span style="color: #abb2bf;">token</span><span style="color: #bbbbbb;">);</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #c678dd;">return</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">Token</span><span style="color: #bbbbbb;">;</span></div>

<div><span style="color: #bbbbbb;">}</span></div>

<div><span style="color: #bbbbbb;">}</span></div>

<div><span style="color: #bbbbbb;">```

### JWT认证

在这里,你可以使用我们下一节所遇到的自定义认证,不过我们还是先学着使用我们最为普通的官方方法。具体的操作非常简单,只需要在我们的容器service中注入一下就可以了。

``` C#</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #abb2bf;">services</span><span style="color: #bbbbbb;">.</span><span style="color: #61afef;">AddAuthentication</span><span style="color: #bbbbbb;">(</span><span style="color: #abb2bf;">JwtBearerDefaults</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">AuthenticationScheme</span><span style="color: #bbbbbb;">)</span></div>

<div><span style="color: #bbbbbb;">.</span><span style="color: #61afef;">AddJwtBearer</span><span style="color: #bbbbbb;">(config</span> <span style="color: #abb2bf;">=></span></div>

<div><span style="color: #bbbbbb;">{</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #abb2bf;">config</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">TokenValidationParameters</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #c678dd;">new</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">TokenValidationParameters</span></div>

<div><span style="color: #bbbbbb;">{</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #abb2bf;">ValidateIssuer</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #d19a66;">true</span><span style="color: #bbbbbb;">,</span><span style="color: #5c6370;font-style: italic;">//是否验证Issuer</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #abb2bf;">ValidateAudience</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #d19a66;">true</span><span style="color: #bbbbbb;">,</span><span style="color: #5c6370;font-style: italic;">//是否验证Audience</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #abb2bf;">ValidateLifetime</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #d19a66;">true</span><span style="color: #bbbbbb;">,</span><span style="color: #5c6370;font-style: italic;">//是否验证失效时间</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #abb2bf;">ValidateIssuerSigningKey</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #d19a66;">true</span><span style="color: #bbbbbb;">,</span><span style="color: #5c6370;font-style: italic;">//是否验证SecurityKey</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #abb2bf;">ValidAudience</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">setting</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">Audience</span><span style="color: #bbbbbb;">,</span><span style="color: #5c6370;font-style: italic;">//Audience</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #abb2bf;">ValidIssuer</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">setting</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">Issuer</span><span style="color: #bbbbbb;">,</span><span style="color: #5c6370;font-style: italic;">//Issuer,这两项和前面签发jwt的设置一致</span></div>

<div><span style="color: #bbbbbb;"></span><span style="color: #abb2bf;">IssuerSigningKey</span> <span style="color: #bbbbbb;"></span> <span style="color: #abb2bf;">=</span> <span style="color: #bbbbbb;"></span> <span style="color: #c678dd;">new</span> <span style="color: #bbbbbb;"></span> <span style="color: #bbbbbb;">SymmetricSecurityKey</span><span style="color: #bbbbbb;">(</span><span style="color: #abb2bf;">Encoding</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">UTF8</span><span style="color: #bbbbbb;">.</span><span style="color: #61afef;">GetBytes</span><span style="color: #bbbbbb;">(</span><span style="color: #abb2bf;">setting</span><span style="color: #bbbbbb;">.</span><span style="color: #abb2bf;">SecretKey</span><span style="color: #bbbbbb;">))</span><span style="color: #5c6370;font-style: italic;">//拿到SecurityKey</span></div>

<div><span style="color: #bbbbbb;">};</span></div>

<div><span style="color: #bbbbbb;">});</span></div>

<div><span style="color: #bbbbbb;">```

这样,就完成了我们的jwt认证过程。

如果我们需要从token中取出我们的信息也非常的简单,利用依赖注入,使用

``` C# services.AddTransient<IGetInfoFromToken, GetInfoFromToken>();</span></div>

<div><span style="color: #bbbbbb;">```

自己创建号这两个接口和类,对httpcontext进行截断,从httpcontext.user中就可以直接取出我们需要的payload。当然也可以使用中间件的方式,这里我们就不再用篇幅进行叙述了。


>如果我的文章帮到了你,请帮忙点个赞,点个关注。谢谢!

>我的掘金:[WarrenRyan](https://juejin.im/user/58ba1512570c3500621152cc)

>

>我的简书:[WarrenRyan](https://www.jianshu.com/u/00635b033ab4)

>

>欢迎关注我的博客获得第一时间更新 [https://blog.tity.online](https://blog.tity.online)

>

>我的Github:[StevenEco](https://github.com/StevenEco)

>

>我的博客园:[WarrenRyan](https://www.cnblogs.com/WarrenRyan/)

validate