JWT

用户在用户微服务中登录,如何又访问其他的微服务而不需要登录了?
这里需要在用户微服务里将用户信息加密生成token。在网关中配置能检验令牌.
在这里插入图片描述
并且,在网关中需要进行权限校验

在这里插入图片描述我们可以采取JWT的方式来实现鉴权校验

一.什么是JWT

JSON Web Token(JWT)是一个非常轻巧的规范,这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。

JWT总结:

JWT是用于微服务之间传递用户信息的一段信息加密字符串,该字符串是一个JSON格式。
各个微服务可以根据该JSON字符串识别用户的身份信息。

二.JWT的构成

一个JWT实际上就是一个字符串,它由三部分组成,头部,载荷与签名

头部(Header)

头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以被表示成一个JSON对象。

{"type":"JWT","alg":"Hs256"}

在头部指明了签名算法是HS256算法。 我们进行BASE64编码http://base64.xpcha.com/,编码后的字符串如下:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

总结:
头部:
1.指定了令牌类型和令牌签名的算法
2.加密方式:Base64

载荷(playload)

载荷就是存放有效信息的地方。
载荷的属性也分三类:

预定义(Registered)
公有(public)
私有(private)

预定义的载荷 (标签中注册的声明(建议但不强制使用))

{
“sub”: “1”,
“iss”: “http://localhost:8000/auth/login”,
“iat”: 1451888119,
“exp”: 1454516119,
“nbf”: 1451888119,
“jti”: “37c107e4609ddbcc9c096ea5ee76c667”,
“aud”: “dev”
}

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

公有的载荷 (自己可以写一些别的属性放进去)
在使用 JWT 时可以额外定义的载荷。为了避免冲突,应该使用 IANA JSON Web Token Registry 中定义好的,或者给额外载荷加上类似命名空间的唯一标识。

私有载荷
私有载荷是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分在客户端可解密.

定义一个payload:

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

然后将其进行base64加密,得到Jwt的第二部分。

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
载荷总结:
主要包括3部分:1.标准中注册的声明
						2.公共的声明(不参与令牌校验)
						3.私有声明(不参与令牌校验)
						1+2+3->Base64加密

签证(signature[签名])

jwt的第三部分是一个签证信息(校验数据是否被篡改),这个签证信息由三部分组成:

header (base64后的)
payload (base64后的)
secret (秘钥->盐)

这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。

TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

将这三部分用.连接成一个完整的字符串,构成了最终的jwt:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6I
kpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7Hg
Q
签名总结:Base64(头)+Base64(载荷)+秘钥(盐)->加密:采用头中指定的算法进行加密->密文(签名)
签名的作用:用于校验令牌是否被篡改

三.JWT的使用

1.依赖引入:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
</dependency>
  1. 创建测试类,代码如下
package com.example.jwt;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.Test;

import java.util.Date;

/**
 * 令牌的生成与解析
 */
public class JwtTest {

    /**
     * 创建令牌
     */
    @Test
    public void testCreateToken(){
        //构建JWT令牌的对象
        JwtBuilder builder = Jwts.builder();
        builder.setIssuer("Test"); //颁发者
        builder.setIssuedAt(new Date()); //颁发时间
        builder.setSubject("JWT 令牌测试"); //主题信息
        builder.signWith(SignatureAlgorithm.HS256,"itcast"); //1.签名算法 2:秘钥(盐)
        //输出令牌
        String token = builder.compact();
        System.out.println(token);

    }
    /**
     * 令牌解析
     */
    @Test
    public void parseToken(){
        String token = "eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJUZXN0IiwiaWF0IjoxNTc1ODY4NDA2LCJzdWIiOiJKV1Qg5Luk54mM5rWL6K-VIn0.PW48aDLfhLwrm9hy-8TcJj8ySudtjTU-odv4pqodvGA";
        Claims claims = Jwts.parser()
                .setSigningKey("itcast") //秘钥(盐)
                .parseClaimsJws(token).getBody();//要解析的令牌对象
        System.out.println(claims.toString()); //解析结果:{iss=Test, iat=1575868406, sub=JWT 令牌测试}
    }
      
}

3.1设置过期时间

有时候我们并不希望签发的token是永久生效的,所有我们可以为token添加一个过期时间.

 @Test
    public void testCreateToken(){
        //构建JWT令牌的对象
        JwtBuilder builder = Jwts.builder();
        builder.setIssuer("Test"); //颁发者
        builder.setIssuedAt(new Date()); //颁发时间
        builder.setExpiration(new Date(System.currentTimeMillis()+20000)); //过期时间20秒
        builder.setSubject("JWT 令牌测试"); //主题信息
        builder.signWith(SignatureAlgorithm.HS256,"itcast"); //1.签名算法 2:秘钥(盐)
        //输出令牌
        String token = builder.compact();
        System.out.println(token);

    }
.setExpiration(date)// 用于设置过期时间 ,参数为Date类型数据

3.2自定义载荷

@Test
   /**
     * 创建令牌
     */
    @Test
    public void testCreateToken(){
        //构建JWT令牌的对象
        JwtBuilder builder = Jwts.builder();
        builder.setIssuer("Test"); //颁发者
        builder.setIssuedAt(new Date()); //颁发时间
        builder.setExpiration(new Date(System.currentTimeMillis()+7*24*3600*1000)); //过期时间
        //自定义载荷信息
        Map<String,Object> userInfo = new HashMap<>();
        userInfo.put("company","101训练营");
        userInfo.put("address","湖北");
        userInfo.put("money",35000);
        //将载荷加入
        builder.addClaims(userInfo);
        builder.setSubject("JWT 令牌测试"); //主题信息
        builder.signWith(SignatureAlgorithm.HS256,"itcast"); //1.签名算法 2:秘钥(盐)
        //输出令牌
        String token = builder.compact();
        System.out.println(token);

    }

解析:

{iss=Test, iat=1575869490, exp=1576474290, address=湖北, money=35000, company=101训练营, sub=JWT 令牌测试}

4.创建工具类

JwtUtil

package com.changgou.entity;

import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;

public class JwtUtil {
    //有效期为    
    public static final Long JWT_TTL = 3600000L;// 60 * 60 *1000  一个小时
    public static final String JWT_KEY = "itcast";

    /**
     * 创建token      * @param id      * @param subject      * @param ttlMillis      * @return
     */
    public static String createJWT(String id, String subject, Long ttlMillis) {
         SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
         long nowMillis = System.currentTimeMillis();
         Date now = new Date(nowMillis);
         if(ttlMillis==null){
            ttlMillis=JwtUtil.JWT_TTL;
         }
        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);
        SecretKey secretKey = generalKey();
        JwtBuilder builder = Jwts.builder()
                .setId(id) //唯一的ID
                .setSubject(subject) // 主题  可以是JSON数据                 
                .setIssuer("admin") // 签发者        
                .setIssuedAt(now) // 签发时间     
                .signWith(signatureAlgorithm, secretKey) //使用HS256对称加 密算法签名, 第二个参数为秘钥              
                .setExpiration(expDate);// 设置过期时间        
                return builder.compact();
    }
    private static SecretKey generalKey() {
        byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值