jwt token 附加用户信息_[入门篇] Jwt 认证

认证和授权的区别

    首先我们要弄清楚认证(Authentication)和授权(Authorization)的区别,以免混淆了。认证是确认的过程中你是谁,而授权围绕是你被允许做什么,即权限。显然,在确认允许用户做什么之前,你需要知道他们是谁,因此,在需要授权时,还必须以某种方式对用户进行身份验证。 

什么是Jwt

    根据维基百科的定义,JSON WEB Token(JWT),是一种基于JSON的、用于在网络上声明某种主张的令牌(token)。JWT通常由三部分组成:头信息(header),消息体(payload)和签名(signature)。

为什么要使用Jwt

    在.NET Core之前对于Web应用程序跟踪用户登录状态最普通的方式则是使用Cookie,当用户点击登录后将对其信息进行加密并响应写入到用户浏览器的Cookie里,当用户进行请求时,服务端将对Cookie进行解密,然后创建用户身份,整个过程都是那么顺其自然,但是这是客户端是基于浏览器的情况,如果是客户端是移动app或者桌面应用程序呢?    

    如果我们使用Json Web Token简称为JWT而不是使用Cookie,此时Token将代表用户,同时我们不再依赖浏览器的内置机制来处理Cookie,我们仅仅只需要请求一个Token就好。这个时候就涉及到Token认证,那么什么是Token认证呢?一言以蔽之:将令牌(我们有时称为AccessToken或者是Bearer Token)附加到HTTP请求中并对其进行身份认证的过程。Token认证被广泛应用于移动端或SPA。

Json Web Token 基础

    JWT由三部分构成,Base64编码的Header,Base64编码的Payload,签名,三部分通过点隔开。

    第一部分以Base64编码的Header主要包括Token的类型和所使用的算法,例如:

{  "alg": "HS265",  "typ": "JWT"}

    第二部分以Base64编码的Payload主要包含的是声明(Claims),例如,如下:

{    "sub": "765032130654732",    "name": "jeffcky"}

    第三部分则是将Key通过对应的加密算法生成签名,最终三部分以点隔开,比如如下形式:

key = 'secretkey'  unsignedToken = encodeBase64(header) + '.' + encodeBase64(payload)  signature = HMAC-SHA256(key, unsignedToken)
token = encodeBase64(header) + '.' + encodeBase64(payload) + '.' + encodeBase64(signature)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiSmVmZmNreSIsImVtYWlsIjoiMjc1MjE1NDg0NEBxcS5jb20iLCJleHAiOjE1NjU2MTUzOTgsIm5iZiI6MTU2MzE5NjE5OCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAxIn0.OJjlGJOnCCbpok05gOIgu5bwY8QYKfE2pOArtaZJbyI

    到这里此时我们应该知道:JWT包含的信息并没有加密,比如为了获取Payload,我们大可通过比如谷歌控制台中的APi(atob)对其进行解码。

    那如我所说既然JWT包含的信息并没有加密,只是进行了Base64编码,岂不是非常不安全呢?当然不是这样,还没说完,第三部分就是签名,虽然我们对Payload(姑且翻译为有效负载),未进行加密,但是若有蓄意更换Payload,此时签名将能充分保证Token无效,除非将签名的Key不小心暴露在光天化日之下,否则必须是安全的。好了,到了这里,我们稍稍讲解了下JWT构成,接下来我们进入如何在.NET Core中使用JWT。

.Net Core 中使用 Jwt

    第一步:安装NuGet包。

Microsoft.AspNetCore.Authentication.JwtBearer

ad0f02278ceeedc602d95aa5b5b52e45.png

Startup类
  • ConfigureServices 添加认证服务

#region Jwtservices.AddAuthentication(options =>{    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;}).AddJwtBearer(options =>{    options.SaveToken = true;    options.RequireHttpsMetadata = false;    options.TokenValidationParameters = new TokenValidationParameters()    {        ValidateIssuer = true,        ValidateAudience = true,        ValidAudience = "https://www.cnblogs.com/chengtian",        ValidIssuer = "https://www.cnblogs.com/chengtian",        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecureKeySecureKeySecureKeySecureKeySecureKeySecureKey"))    };});#endregion
  • Configure 配置认证中间件

 app.UseAuthentication();//认证中间件,放在其他中间件的前面

创建一个token

  • 添加一个Token的Model命名为TokenDto

namespace MyWeb.Model{    ///     /// Token    ///     public class TokenDto    {        ///         /// Token        ///         public string Token { get; set; }        ///         /// 过期时间        ///         public string Expiration { get; set; }    }}
  • 添加一个生成Token的帮助类

using Microsoft.IdentityModel.Logging;using Microsoft.IdentityModel.Tokens;using MyWeb.Model;using System;using System.IdentityModel.Tokens.Jwt;using System.Security.Claims;using System.Text;namespace MyWeb.Api.Auth{    ///     /// 获取Token    ///     public static class TokenHelper    {        ///         /// 获取Token        ///         ///         ///         ///         public  static TokenDto CreateToken(string userName, string password)        {            //从数据库验证用户名,密码             //验证通过 否则 返回Unauthorized            if (!(userName == "admin" && password == "123456"))            {                return null;            }            var claims = new[]            {                new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}") ,//当前时间                new Claim (JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddMinutes(30)).ToUnixTimeSeconds()}"),//过期时间                new Claim(ClaimTypes.NameIdentifier, "1"),//用户Id,                new Claim(ClaimTypes.Name, userName),//用户名                new Claim("Role", "admin")//用户角色             };            IdentityModelEventSource.ShowPII = true;            //签名秘钥 可以放到json文件中            var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SecureKeySecureKeySecureKeySecureKeySecureKeySecureKey"));            var token = new JwtSecurityToken(                   issuer: "https://www.cnblogs.com/chengtian",                   audience: "https://www.cnblogs.com/chengtian",                   expires: DateTime.Now.AddHours(2),                   claims: claims,                   signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)                   );            return new TokenDto()            {                Token = new JwtSecurityTokenHandler().WriteToken(token),                Expiration = token.ValidTo.ToLongDateString()            };        }    }}
  • 创建一个控制器 AuthenticateController

[HttpGet]public ActionResultGetToken(string userName, string password){    var token = TokenHelper.CreateToken(userName, password);    return Ok(token);}

    测试一下,给之前的CompaniesController 控制器加上认证。你可以直接加在控制器上,也可以加在具体的某个方法上。

70d280f812b7e1bddd14a421ccb4e3ab.png

        最后我们来测试一下。

43a2cc770e069a612db0a4461d74d65f.png

    此时我们的Api已经收到了保护,我们获取一下Token。

f9b50551dce853c4246626decbcc08f8.png

    获取成功后,给接口请求加上 Token 。请求成功。

1fcf4c136b37b1d24813e62fdc691050.png

    我们在登录完成后要获取登录的用户名或者Id,我们可以通过下面的这种方式获取。

User.FindFirst(ClaimTypes.NameIdentifier)?.Value

    调试可以看到我们获取到的用户Id是1

ba5c0d34a1fa5d3e934139c8a9ee5f43.png

    因为我们存进去的是1

00df3251acf428ffc158a9009687b72f.png

    同样的方法获取一下用户名,这样就可以在授权成功后拿到用户Id进行操作了

e1376990e109c01ec9db24f16f09e239.png

dff968afd943f9f1ffab2304c264a1a1.png

感谢您的关注,您分享和点赞,是我分享路上最大的动力

留言区

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值