GVKun编程网logo

JWT(JSON Web Token) Java与.Net简单编码实现(jwt.encode)

3

本文将为您提供关于JWT(JSONWebToken)Java与.Net简单编码实现的详细介绍,我们还将为您解释jwt.encode的相关知识,同时,我们还将为您提供关于.NetCore授权认证方案JW

本文将为您提供关于JWT(JSON Web Token) Java与.Net简单编码实现的详细介绍,我们还将为您解释jwt.encode的相关知识,同时,我们还将为您提供关于.Net Core授权认证方案JWT(JSON Web Token)初探、Asp.net Core 3.1 Web API添加jwt验证(二):用单例模式简单封装token生成器JwtGenerator、asp.net core 中的Jwt(Json Web Token)的使用详解、JSON WEB TOKEN (JWT)的实用信息。

本文目录一览:

JWT(JSON Web Token) Java与.Net简单编码实现(jwt.encode)

JWT(JSON Web Token) Java与.Net简单编码实现(jwt.encode)

参考

  • JWT(JSON WEB TOKENS)-一种无状态的认证机制
  • 基于Token的WEB后台认证机制
  • 各种语言版本的基于HMAC-SHA256的base64加密

Java与.Net实现实现

// java HMacsha256
private static final  String MAC_INSTANCE_NAME = "HMacSHA256";

public static String Hmacsha256(String secret, String message) throws NoSuchAlgorithmException, InvalidKeyException {
    Mac hmac_sha256 = Mac.getInstance(MAC_INSTANCE_NAME);
    SecretKeySpec key = new SecretKeySpec(secret.getBytes(), MAC_INSTANCE_NAME);
    hmac_sha256.init(key);
    byte[] buff = hmac_sha256.doFinal(message.getBytes());
    return Base64.encodeBase64URLSafeString(buff);
}

// java jwt
@Test
public void testJWT() throws InvalidKeyException, NoSuchAlgorithmException {
    String secret = "eerp";
    String header = "{\"type\":\"JWT\",\"alg\":\"HS256\"}";
    String claim = "{\"iss\":\"cnooc\", \"sub\":\"yrm\", \"username\":\"yrm\", \"admin\":true}";

    String base64Header = Base64.encodeBase64URLSafeString(header.getBytes());
    String base64Claim = Base64.encodeBase64URLSafeString(claim.getBytes());
    String signature = ShaUtil.Hmacsha256(secret, base64Header + "." + base64Claim);

    String jwt = base64Header + "." + base64Claim  + "." + signature;
    System.out.println(jwt);
}

 

 // c# Hmacsha256 protected String HMacSha256Hash(String key, String message) { var keyBytes = Encoding.UTF8.GetBytes(key); using (var hmacsha256 = new HMACSHA256(keyBytes)) { var buffer = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(message)); var b64 = Base64UrlSafeString(buffer); return b64; } } protected String Base64UrlSafeString(Byte[] bytes) { var b64 = Convert.ToBase64String(bytes); return b64.Replace("=", "").Replace("+", "-").Replace("/", "_"); } // c# jwt [Test] public void testJWT() { String secret = "eerp"; String header = "{\"type\":\"JWT\",\"alg\":\"HS256\"}"; String claim = "{\"iss\":\"cnooc\", \"sub\":\"yrm\", \"username\":\"yrm\", \"admin\":true}"; var encoding = Encoding.UTF8; var base64Header = Base64UrlSafeString(encoding.GetBytes(header)); var base64Claim = Base64UrlSafeString(encoding.GetBytes(claim)); var signature = HMacSha256Hash(secret, base64Header + "." + base64Claim); var jwt = base64Header + "." + base64Claim + "." + signature; Console.WriteLine(jwt); }

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

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

一、前言

现在越来越多的项目或多或少会用到JWT,为什么会出现使用JWT这样的场景的呢?

假设现在有一个APP,后台是分布式系统。APP的首页模块部署在上海机房的服务器上,子页面模块部署在深圳机房的服务器上。此时你从首页登录了该APP,然后跳转到子页面模块。session在两个机房之间不能同步,用户是否需要重新登录?

传统的方式(cookie+session)需要重新登录,用户体验不好。session共享(在多台物理机之间传输和复制session)方式对网络IO的压力大,延迟太长,用户体验也不好。

说到这大家可能会想到,用服务器的session_id存储到cookies中也能做到,为什么非要用token呢?网上有许多文章来比较token和session的优缺点,其实,开发web应用的话用哪种都行。但如果是开发api接口,前后端分离,最好使用token,为什么这么说呢,因为session+cookies是基于web的。但是针对 api接口,可能会考虑到移动端,app是没有cookies和session的。

Session方式存储用户信息的最大问题在于要占用大量服务器内存,增加服务器的开销。

而JWT方式将用户状态分散到了客户端中,可以明显减轻服务端的内存压力。Session的状态是存储在服务器端,客户端只有session id;而Token的状态是存储在客户端

二、原理

JSON Web Token(缩写 JWT)

JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,以后,用户与服务端通信的时候,都要发回这个 JSON 对象。

服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名。

服务器就不保存任何 session 数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。

三、组合

JWT 的三个部分依次是:Header(头部)、Payload(负载)、Signature(签名)

写成一行,就是下面的样子。

Header.Payload.Signature

1、Header头部

header典型的由两部分组成:token的类型(“JWT”)和算法名称(比如:HMAC SHA256或者RSA等等)

{
    "alg": "HS256", //alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256)
    "typ": "JWT"   //typ属性表示这个令牌(token)的类型(type)
}

然后用Base64对这个JSON编码就得到JWT的第一部分

2、Payload负载

JWT的第二部分是payload,它包含声明(要求)。声明是关于实体(通常是用户)和其他数据的声明

JWT 规定了7个官方字段

  • iss (issuer):签发人
  • exp (expiration time):过期时间
  • sub (subject):主题
  • aud (audience):受众
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间
  • jti (JWT ID):编号

除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

注意,不要在JWT的payload或header中放置敏感信息,除非它们是加密的

3、Signature签名

Signature 部分是对前两部分的签名,防止数据篡改。

签名是用于验证消息在传递过程中有没有被更改,并且,对于使用私钥签名的token,它还可以验证JWT的发送方是否为它所称的发送方。

为了得到签名部分,你必须有编码过的header、编码过的payload、一个秘钥。签名算法是header中指定的那个,然对它们签名即可。按照下面的公式产生签名。

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。

四、开始

1、客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。

此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。

Authorization: Bearer <token>

2、JWT 就放在 POST 请求的数据体里面,那么跨源资源共享(CORS)将不会成为问题,因为它不使用cookie。

  • 应用(或者客户端)向授权服务器请求授权。例如,如果用授权码流程的话,就是/oauth/authorize
  • 当授权被许可以后,授权服务器返回一个access token给应用
  • 应用使用access token访问受保护的资源(比如:API)

五、特点

1.JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。

2.JWT 不加密的情况下,不能将秘密数据写入 JWT。

3.JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

4.JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

注意:

JWT 是 JSON 格式的被加密了的字符串

JWT 的核心是密钥,就是 JSON 数据。这是你关心的,并希望安全传递出去的数据。JWT 如何做到这一点,并使你信任它,就是加密签名。

被篡改之后

六、总结

参考官方文档:JSON Web Tokens

到此这篇关于.Net Core授权认证方案JWT的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持。

您可能感兴趣的文章:
  • JWT Json Web Token全面详解
  • asp.net core 中的Jwt(Json Web Token)的使用详解
  • JSON Web Token(JWT)原理入门教程详解
  • 详解JSON Web Token 入门教程
  • JSON Web Tokens的实现原理
  • Json Web Token在前后端实践思考分析

Asp.net Core 3.1 Web API添加jwt验证(二):用单例模式简单封装token生成器JwtGenerator

Asp.net Core 3.1 Web API添加jwt验证(二):用单例模式简单封装token生成器JwtGenerator

提出问题

在上一篇我们搭建了一个基础的项目框架,并介绍了怎么向其中引入jwt鉴权,不知小伙伴们有没有注意到我们用于生成token的代码片段:

[HttpGet("login")]
public ActionResult Login(string username, string password)
{
    if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
    {
        // token中的claims用于储存自定义信息,如登录之后的用户id等
        var claims = new[]
        {
            new Claim("userId", username)
        };
        // 获取SecurityKey
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration.GetSection("Authentication")["SecurityKey"]));
        var token = new JwtSecurityToken(
            issuer: _configuration.GetSection("Authentication")["Issure"],                    // 发布者
            audience: _configuration.GetSection("Authentication")["Audience"],                // 接收者
            notBefore: DateTime.Now,                                                          // token签发时间
            expires: DateTime.Now.AddMinutes(30),                                             // token过期时间
            claims: claims,                                                                   // 该token内存储的自定义字段信息
            signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)    // 用于签发token的秘钥算法
        );
        // 返回成功信息,写出token
        return Ok(new { code = 200, message = "登录成功", data = new JwtSecurityTokenHandler().WriteToken(token) });
    }
    // 返回错误请求信息
    return BadRequest(new { code = 400, message = "登录失败,用户名或密码为空" });
}

在这段代码里,我们着重看下面这一段:

// token中的claims用于储存自定义信息,如登录之后的用户id等
var claims = new[]
{
    new Claim("userId", username)
};
// 获取SecurityKey
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration.GetSection("Authentication")["SecurityKey"]));
var token = new JwtSecurityToken(
    issuer: _configuration.GetSection("Authentication")["Issure"],                    // 发布者
    audience: _configuration.GetSection("Authentication")["Audience"],                // 接收者
    notBefore: DateTime.Now,                                                          // token签发时间
    expires: DateTime.Now.AddMinutes(30),                                             // token过期时间
    claims: claims,                                                                   // 该token内存储的自定义字段信息
    signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)    // 用于签发token的秘钥算法
);
// 返回成功信息,写出token
return Ok(new 
{ 
    code = 200, 
    message = "登录成功", 
    data = new JwtSecurityTokenHandler().WriteToken(token) 
});

从上面代码可以看出,要想生成一个完整的token,我们至少需要知道6个类:

  • Claim:向token中添加自定义信息
  • SymmetricSecurityKey:使用对称方法生成秘钥
  • JwtSecurityToken:初始化JwtToken
  • SigningCredentials:使用秘钥以及算法生成加密证书
  • SecurityAlgorithms:保存了加密方法字符串的常量
  • JwtSecurityTokenHandler:JwtToken处理器

理论上来说,框架封装时对外暴露的类型及方法应越少越好(使用者只要知道尽可能少的几个类就可以实现预期的功能),基于此出发点,我们可以使用设计模式对这个生成token的过程进行改造。

开始改造

先说一说什么是单例模式:

单例模式是GoF总结的23种常见设计模式之一,它保证了在整个程序的运行过程中,有且只有一个调用类的实例。

接下来,就使用单例模式来创建新的Token生成器——JwtGenerator

创建JwtGenerator类

在解决方案中右键项目,创建Services目录,并在其下创建JwtGenerator.cs文件,代码如下:

using System;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authentication;
using System.IdentityModel.Tokens.Jwt;
using System.Collections.Generic;
using System.Text;

namespace JwtTest.Services
{
    public class JwtGenerator
    {
        // static保证了本类的对象只有一个,且封装在本类内部
        private static JwtGenerator _generator = null;

        // 用于产生JwtToken的本体生成器
        private JwtSecurityToken token = null;

        // token自定义的Claim信息
        private IEnumerable<Claim> Claims { get; set; } = null;

        // 定义token基础信息
        // token的颁发者
        private string Issuer { get; set; } = string.Empty;
        // token的接收者
        private string Audience { get; set; } = string.Empty;
        // 用于颁布token的秘钥
        private string SecurityKey { get; set; } = string.Empty;
        // token的秘钥算法
        private string Alg { get; set; } = SecurityAlgorithms.HmacSha256;
        // token的颁发时间,默认取当前时间
        private DateTime NotBefore { get; set; } = DateTime.Now;
        // token的过期时间,默认30分钟后
        private DateTime Expires { get; set; } = DateTime.Now.AddMinutes(30);

        // 构造函数使用private定义,这样外面就无法通过new构造函数来实例化JwtGenerator类
        private JwtGenerator() { }

        // 这里使用了C#新版本的写法,等同于:
        // public static JwtGenerator GetInstance() {
        //     if (_generator == null) {
        //         _generator = new JwtGenerator();
        //     }
        //     return _generator;
        // }
        // 第一次调用GetInstance时,会实例化static标注的_generator对象,后续调用会返回已经实例化的对象,从而保证本类只有一个对象
        public static JwtGenerator GetInstance() => _generator ??= new JwtGenerator();

        // 添加自定义信息
        public JwtGenerator AddClaims(IEnumerable<Claim> claims)
        {
            _generator.Claims = claims;
            return _generator;
        }

        // 添加发布者
        public JwtGenerator AddIssuer(string issuer)
        {
            _generator.Issuer = issuer;
            return _generator;
        }

        // 添加接收者
        public JwtGenerator AddAudience(string audience)
        {
            _generator.Audience = audience;
            return _generator;
        }

        // 添加发布时间
        public JwtGenerator AddNotBefore(DateTime notBefore)
        {
            _generator.NotBefore = notBefore;
            return _generator;
        }

        // 添加过期时间
        public JwtGenerator AddExpires(DateTime expires)
        {
            _generator.Expires = expires;
            return _generator;
        }

        // 添加用于生成token的秘钥
        public JwtGenerator AddSecurityKey(string securityKey)
        {
            _generator.SecurityKey = securityKey;
            return _generator;
        }

        // 添加token生成算法
        public JwtGenerator AddAlgorithm(string securityAlgorithm)
        {
            _generator.Alg = securityAlgorithm;
            return _generator;
        }

        // 生成token
        public string Generate()
        {
            // 必备参数,若没有初始化,则抛出空指针异常
            if (string.IsNullOrEmpty(_generator.SecurityKey)) throw new NullReferenceException("SecurityKey is null");
            if (string.IsNullOrEmpty(_generator.Issuer)) throw new NullReferenceException("Issuer is null");
            if (string.IsNullOrEmpty(_generator.Audience)) throw new NullReferenceException("Audience is null");
            // 调用Generate方法之前,已经调用过上面的Add方法添加了对应的初始化token的参数
            _generator.token = new JwtSecurityToken(
                issuer: this.Issuer,
                audience: this.Audience,
                claims: this.Claims,
                notBefore: this.NotBefore,
                expires: this.Expires,
                // 创建token颁发证书
                signingCredentials: new SigningCredentials(
                    // 使用秘钥字符串跟加密算法生成加密token的对称加密秘钥
                    key: new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this.SecurityKey)),
                    algorithm: this.Alg
                )
            );
            // 调用Token处理器,写出token字符串
            return new JwtSecurityTokenHandler().WriteToken(token);
        }
    }
}

上述代码只是对token生成器的简单封装,token的接收者可能有很多个,这时我们可以参考上面的AddXXXX方法,添加AddAudiences功能,其他功能也一样可以自定义。

接下来我们来体验一下刚刚创建的JwtGenerator

使用JwtGenerator

打开AuthController,添加一个新方法Signin()

// GET: api/auth/signin
[HttpGet("signin")]
[AllowAnonymous]
public ActionResult Signin(string username, string password)
{
    if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
    {
        // 调用JwtGenerator,生成一个新的token
        string token = JwtGenerator.GetInstance()
                                   .AddIssuer(_configuration.GetSection("Authentication")["Issure"])
                                   .AddAudience(_configuration.GetSection("Authentication")["Audience"])
                                   .AddSecurityKey(_configuration.GetSection("Authentication")["SecurityKey"]);
                                   .AddClaims(new[]
                                   {
                                       new Claim("userId", username)
                                   }).Generate();
        return Ok(new { code = 200, message = "登录成功", data = new { token } });
    }
    return BadRequest(new { code = 400, message = "登录失败,用户名或密码不能为空" });
}

运行程序,使用Postman测试GET /api/auth/signin接口吧。

再次思考

经过上面步骤,我们已经封装好了JwtGenerator,代码调用虽然简单了,但整体看上去并没有什么很大的优化。

请跟随我的脚步继续思考

实际开发过程中我们经常会遇到这样一个场景:

用户登录时颁发一个token、用户需要重置密码时颁发一个token、敏感资源访问时又颁发一个token

token经常需要携带允许访问的动作信息供后端校验,来保证自身不被用于其他接口

也就是说在整个后端代码中可能有不少地方我们都会生成新的token,难道每次我们都需要这么写?

string token = JwtGenerator.GetInstance()
                           .AddIssuer(_configuration.GetSection("Authentication")["Issure"])
                           .AddAudience(_configuration.GetSection("Authentication")["Audience"])
                           .AddSecurityKey(_configuration.GetSection("Authentication")["SecurityKey"]);
                           .AddClaims(new[]
                           {
                               new Claim("userId", username)
                           }).Generate();

其实不然,仔细思考一下,不管新的token怎么变,总是有一些参数不会变的,比如说秘钥。

那么由此,我们就可以得到下面的写法

打开Startup.cs,在ConfigureServices方法中添加下面代码:

// 配置Token生成器
JwtGenerator.GetInstance()
            .AddIssuer(_configuration.GetSection("Authentication")["Issure"])
            .AddAudience(_configuration.GetSection("Authentication")["Audience"])
            .AddSecurityKey(_configuration.GetSection("Authentication")["SecurityKey"]);

因为我这个项目,Issuer跟Audience,SecurityKey都不会变,所以我在Startup中拿到JwtGenerator的实例,并初始化了其中不会改变的配置。

这样我就可以在需要的地方这么调用它:

// 登录鉴权动作
string token = JwtGenerator.GetInstance()
                           .AddClaims(new[]
                           {
                               new Claim("action", "login"),
                               new Claim("uid", username)
                           }).Generate();
// 重置密码动作
string token = JwtGenerator.GetInstance()
                           .AddClaims(new[]
                           {
                               new Claim("action", "reset"),
                               new Claim("uid", username)
                           }).Generate();
// 敏感资源访问动作
string token = JwtGenerator.GetInstance()
                           .AddClaims(new[]
                           {
                               new Claim("action", "oauth"),
                               new Claim("source", "/api/admin/xxx")
                           }).Generate();

怎么样。这token生成操作可还行?

asp.net core 中的Jwt(Json Web Token)的使用详解

asp.net core 中的Jwt(Json Web Token)的使用详解

简单描述: session不支持 分布式 并且在服务器存储一份用户登录的信息,这份登录信息会在响应时传递给浏览器,告诉其保存为cookie,以便下次请求时发送给我们的应用

Jwt描述:

1.状态保证在客户端,而非服务器端。天然适合分布式系统。

2.签名保证了客户端无法数据造假。

3.性能更高,不需要和 中心状态服务器通信(如Redis),纯内存的计算

JWT是由三段信息构成的,将这三段信息文本用.链接一起就构成了Jwt字符串

第一部分我们称它为头部(header 明文 的加密算法类型),第二部分我们称其为载荷(payload, 明文的各种 自定义 信息),第三部分是签证(signature只有服务器端才知道的密钥).

不要在 jwt中 传入 非常敏感 信息 ,因为客户端 可以解析 出明文

流程:服务器 生成 Jwt 颁发给 客户端 ,每次客户端 请求 带上 Jwt,服务器端在做效验。

下面使用 一个 案例 来说明 JWT的使用

1.设置JWT配置实体 JWTSetting.cs 用于注入

namespace aspnetcore013
{
    public class JWTSetting
    {
        public string Key { get; set; } // JWT 服务端的 key
        public long OutTime { get; set; } //设置过期秒数
    }
}

2.在 appsettings.json 文件中配置如下

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "JWT": {
    "key": "xcv24fds*/*=-.lj?./54oi@%$^*ouio",
    "OutTime": 3600
  }
}

 3.1.在 Program.cs 文件中 配置 JWT配置 如下 

builder.Services.Configure<JWTSetting>(builder.Configuration.GetSection("JWT"));
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(opt =>
    {
        var JWTsetting = builder.Configuration.GetSection("JWT").Get<JWTSetting>();
        byte[] byteKeys = Encoding.UTF8.GetBytes(JWTsetting.Key);
        var securityKey = new SymmetricSecurityKey(byteKeys);
        opt.TokenValidationParameters = new TokenValidationParameters()
        {
            ValidateIssuer = false,
            ValidateAudience = false,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = securityKey
        };
    });

3.2 最后 还有 在添加 app.UseAuthentication(); 需要在 app.UseAuthorization(); 之前 

app.UseAuthentication();

4.登录成功 用于生成JWT 字符串

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
 
namespace aspnetcore013.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class Test3Controller : ControllerBase
    {
        //用于 依赖注入
        private readonly IOptionsSnapshot<JWTSetting> _settings;
 
        //注入 设置
        public Test3Controller(IOptionsSnapshot<JWTSetting> settings)
        {
            _settings = settings;
        }
 
        [HttpGet]
        public ActionResult<string> Login(string userName,string passWord)
        {
            if(userName=="zhangsan"&& passWord == "123456")
            {
                //这里已经 表明 登录 成功 
                //Claim为 JWT第二阶段的 payload
                List<Claim> claims = new List<Claim>();
                claims.Add(new Claim(ClaimTypes.NameIdentifier, "66"));
                claims.Add(new Claim(ClaimTypes.Name, "zhangsan"));
                claims.Add(new Claim("Wechat", "jiujiu56"));//自定义 type名称
                claims.Add(new Claim(ClaimTypes.Role, "admin"));
                //下面为生成 JWT
                string configkey = _settings.Value.Key;
                DateTime outTime = DateTime.Now.AddSeconds(_settings.Value.OutTime);
                byte[] byteKey = Encoding.UTF8.GetBytes(configkey);
                var securityKey = new SymmetricSecurityKey(byteKey);
                var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
                //设置 JWT第二阶段的 payload 和过期 时间 和 效验算法
                var securityToken = new JwtSecurityToken(claims: claims, expires: outTime, signingCredentials: credentials);
                string jwt =new JwtSecurityTokenHandler().WriteToken(securityToken);
                return jwt;
            }
            else
            {
                return BadRequest("登录失败");
            }
        }
    }
}

5.标记 需要 授权的 控制器或方法

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
 
namespace aspnetcore013.Controllers
{
 
    [Route("api/[controller]/[action]")]
    [ApiController]
    [Authorize]  //在控制器上 加入这个[Authorize]
                 //则 这个控制器 下所有 方法必须 登录验证
                 //如果在 方法上加 那么 这个方法 必须 登录验证
    public class Test4Controller : ControllerBase
    {
        [HttpGet]
        public string demo1()
        {
            //获取 当前登录成功的用户 Claim的值
            var claim = this.User.FindFirst(ClaimTypes.Name);
            return "666"+ claim.Value;
        }
 
        [HttpGet]
        [AllowAnonymous] //在方法中 使用 [AllowAnonymous] 
                         //可以 排除 本方法 使用 授权 不必登录验证 就可使用
        public string demo2()
        {
            return "777";
        }
        [HttpGet]
        [Authorize(Roles ="admin")] //可以使用 Role进行
                                   //角色的控制 [Authorize(Roles ="admin")]
                                   //这里表示 必须要 有登录权限并且角色为 admin
        public string demo3()
        {
            return "888";
        }
    }
}

6.访问 [Authorize] 授权的 方法或控制器 必须在 提交协议头 加上 Authorization:Bearer JWT数据

注意:Bearer 和 JWT数据之间 要有 一个 空格 。JWT数据之后不能 参杂 任何额外数据

如果 退出 JWT 一般把 JWT删除 就好。在多端 删除即可 JWT还可以有 过期时间,上面代码已经 阐述 清楚了。

引入 Microsoft.AspNetCore.Authentication.JwtBearer 包

到此这篇关于asp.net core 中的Jwt(Json Web Token)的使用的文章就介绍到这了,更多相关asp.net core  Jwt使用内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

您可能感兴趣的文章:
  • JWT Json Web Token全面详解
  • .Net Core授权认证方案JWT(JSON Web Token)初探
  • JSON Web Token(JWT)原理入门教程详解
  • 详解JSON Web Token 入门教程
  • JSON Web Tokens的实现原理
  • Json Web Token在前后端实践思考分析

JSON WEB TOKEN (JWT)

JSON WEB TOKEN (JWT)

JSON WEB TOKEN

JSON WEB TOKEN简称为JWT,是一个基于JSON的开放标准,用于通信双方之间传递安全信息的简洁的、URL安全的表述性声明规范,经常用于身份验证。

结构

JWT有三部分组成,他们之间用.分隔,这三部分分别是HeaderPayloadSignature,结构如下

Header.Payload.Signature

jwt.io给予的实例

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

对于这个例子,其三部分组成分别为

// header
{
  "alg": "HS256","typ": "JWT"
}

// Payload
{
  "sub": "1234567890","name": "John Doe","iat": 1516239022
}

// Signature
HMACSHA256(
  base64UrlEncode(header) + "." +base64UrlEncode(payload),"your-256-bit-secret"
)

Header头部,其由两部分组成:声明类型和算法名称,在本例中的Token类型为jwt,加密算法为HMAC-SHA256。将Header进行BASE64URL算法编码,即可得到jwt的第一部分,注意BASE64URL算法编码与BASE64编码略有不同,BASE64URL需要将BASE64中输出中的+替换为减号-/替换为_,而且没有标准的BASE64填充,把=去掉。

base64UrlEncode({"alg": "HS256","typ": "JWT"}) === "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";

Payload

Payload有效载荷,其为JWT的主体,这里可以存放主体数据信息,Payload包含三个部分,标准中注册的声明、公共的声明、私有的声明

标准中注册的声明 (建议但不强制使用)

  • iss: jwt签发者
  • sub: jwt主题
  • aud: jwt接收者
  • exp: jwt过期时间
  • nbf: jwt生效时间
  • iat: jwt的签发时间
  • jti: jwt的唯一身份标识,避免重放攻击

公共声明

可以在公共声明添加任何信息,我们一般会在里面添加用户信息和业务信息,但是不建议添加敏感信息,因为公共声明部分可以在客户端解密,除非此信息是加密的。

私有声明

私有声明是服务器和客户端共同定义的声明,同样这里不建议添加敏感信息。

base64UrlEncode({"sub": "1234567890","iat": 1516239022}) === "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ";

Signature

Signature哈希签名,其通过JWTHeader定义的算法,将前两部分数据进行编码后哈希来生成签名,主要是确保数据不会被篡改。

HMACSHA256( base64UrlEncode(header) + "." +base64UrlEncode(payload),"your-256-bit-secret") === "SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

优点

  • 无状态和可拓展性,服务器将JWT存储到客户端以后不存在状态或者会话信息,易于拓展
  • 可以预防CSRF攻击,由于使用JWT一般放置于请求头的Authorization: Bearer ${JWT}字段中而不使用Cookie可以有效防止CSRF攻击
  • payload部分可以存储一些其他业务逻辑所必要的非敏感信息,可以减轻服务端压力
  • JWT的跨语言支持性,由于json与加密算法的通用性,在多数语言中都能得到支持
  • 相对于OAuth2更加轻量,但是其应用场景有所区别,OAuth2是一种授权框架,通常用于第三方应用授权,JWT是一种认证协议,用于前后端分离的用户认证以及后端API的保护

缺点

  • 一旦签发无法更新,如果想更新数据或者续签,必须重新签发
  • 无法废弃,在JWT设置的过期时间到达之前,JWT始终有效
  • Payload是使用BASE64URL编码的,并没有加密,因此jwt中在未加密的情况下不能存储敏感数据
  • JWT本身包含认证信息,因此一旦信息泄露,任何人都可以获得令牌的所有权限,所以JWT的有效期不宜设置太长。
  • 伪造JWT,攻击者拥有一个JWT,可以伪造Header中的algnone来验证身份,理论上这是符合JWT规范要求的,而且有些库中都默认实现此验证,所以需要禁用algnone的请求。
  • 爆破HMAC密钥,由于用户可以拿到完整的JWT,其中就包含加密算法,用户可以根据JWT中信息爆破密钥,而且整个操作可以本地完成,不需要与服务端交互。

相关

CSRF https://github.com/WindrunnerMax/EveryDay/blob/master/browser/CSRF%E8%B7%A8%E7%AB%99%E8%AF%B7%E6%B1%82%E4%BC%AA%E9%80%A0.md
XSS https://github.com/WindrunnerMax/EveryDay/blob/master/browser/XSS%E8%B7%A8%E7%AB%99%E8%84%9A%E6%9C%AC%E6%94%BB%E5%87%BB.md
Cookie与Session https://github.com/WindrunnerMax/EveryDay/blob/master/HTML/Cookie%E4%B8%8ESession.md

参考

https://www.freebuf.com/vuls/219056.html
https://blog.csdn.net/qq_28165595/article/details/80214994

关于JWT(JSON Web Token) Java与.Net简单编码实现jwt.encode的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于.Net Core授权认证方案JWT(JSON Web Token)初探、Asp.net Core 3.1 Web API添加jwt验证(二):用单例模式简单封装token生成器JwtGenerator、asp.net core 中的Jwt(Json Web Token)的使用详解、JSON WEB TOKEN (JWT)的相关信息,请在本站寻找。

本文标签: