JWT 实现微服务鉴权

什么是微服务鉴权:
判断用户是否有权限进行微服务的访问,微服务的鉴权比较适合在网关中进行权限的校验
JWT 实现微服务鉴权_第1张图片
我们可以采用 JWT的方式来实现鉴权校验
JWT
JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名
1.头部(Header):
头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以被表示成一个JSON对象 如:
{“typ”:“JWT”,“alg”:“HS256”} 在头部指明了签名算法是HS256算法。 我们进行BASE64编码http://base64.xpcha.com/,编码后的字符串如下:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
2.载荷(playload)
载荷就是存放有效信息的地方。
定义一个payload:
{“sub”:“1234567890”,“name”:“John Doe”,“admin”:true}
然后将其进行base64加密,得到Jwt的第二部分: eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
3.签证(signature)
jwt的第三部分是一个签证信息,这个签证信息由三部分组成:
header (base64后的)
payload (base64后的)
secret
这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分:TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
将这三部分用.连接成一个完整的字符串,构成了最终的jwt:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

JJWT 签发与验证token
JWT令牌生成步骤:
1.导入对应的坐标

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
</dependency>

2.创建测试类,代码如下:

package com.sq.Demo;

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

import java.util.Date;

public class Demo1_JWT {
    public static void main(String[] args) {
        JwtBuilder jwtBuilder = Jwts.builder()
                .setId("888") //设置唯一编号
                .setSubject("小白")   //设置主题,可以是JSON数据
                .setIssuedAt(new Date())//设置签发日期
                .signWith(SignatureAlgorithm.HS256, "abcd");//设置签名,使用HS256算法,地二个参数为密钥,暂时设置为abcd

        String jwtToken = jwtBuilder.compact(); //生成jwt令牌
        System.out.println(jwtToken);
        //输出结果为:eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1OTE1MTY5OTF9.HyEkdq18Jca65jrs0f3BYBYafgLG9goJy7mPT9FKr-4
    }
}

解析token
我们刚才已经创建了 token ,在web应用中这个操作是由服务端进行然后发给客户端,客
户端在下次向服务端发送请求时需要携带这个token(这就好像是拿着一张门票一样),
那服务端接到这个token 应该解析出token中的信息(例如用户id),根据这些信息查询数
据库返回相应的结果。

package com.sq.Demo; 

import io.jsonwebtoken.*;
import java.util.Date;

public class Demo1_JWT {
    public static void main(String[] args) {
        JwtBuilder jwtBuilder = Jwts.builder()
                .setId("888") //设置唯一编号
                .setSubject("小白")   //设置主题,可以是JSON数据
                .setIssuedAt(new Date())//设置签发日期
                .signWith(SignatureAlgorithm.HS256, "abcd");//设置签名,使用HS256算法,地二个参数为密钥,暂时设置为abcd

        String jwtToken = jwtBuilder.compact(); //生成jwt令牌
        System.out.println(jwtToken);
        //输出结果为:eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1OTE1MTY5OTF9.HyEkdq18Jca65jrs0f3BYBYafgLG9goJy7mPT9FKr-4

        
        
       /* .setSigningKey("abcd") 设置签名密钥,必须要和生成的密钥一致
        .parseClaimsJws(jwtToken) 对jwt进行解析
        .getBody();//获取jwt令牌里内容*/
        Claims abcd = Jwts.parser().setSigningKey("abcd").parseClaimsJws(jwtToken).getBody();
        System.out.println(abcd);
        //输出结果为:{jti=888, sub=小白, iat=1591517491}
    }
}

试着将token或签名秘钥篡改一下,会发现运行时就会报错,所以解析token也就是验证token

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

package com.sq.Demo;

import io.jsonwebtoken.*;

import java.util.Date;

public class Demo1_JWT {
    public static void main(String[] args) {

        long timeMillis = System.currentTimeMillis();
        timeMillis += 1800000L;
        Date date = new Date(timeMillis);

        JwtBuilder jwtBuilder = Jwts.builder()
                .setId("888") //设置唯一编号
                .setSubject("小白")   //设置主题,可以是JSON数据
                .setIssuedAt(new Date())//设置签发日期
                .setExpiration(date) //设置令牌30分钟后过期
                .signWith(SignatureAlgorithm.HS256, "abcd");//设置签名,使用HS256算法,地二个参数为密钥,暂时设置为abcd

        String jwtToken = jwtBuilder.compact(); //生成jwt令牌
        System.out.println(jwtToken);
        //输出结果为:eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1OTE1MTgyOTEsImV4cCI6MTU5MTUyMDA5MX0.sVg00VgEN21f7r40fu7ODc1dRUAHxSGOP_EJmiTYi8o



       /* .setSigningKey("abcd") 设置签名密钥,必须要和生成的密钥一致
        .parseClaimsJws(jwtToken) 对jwt进行解析
        .getBody();//获取jwt令牌里内容*/
        Claims abcd = Jwts.parser().setSigningKey("abcd").parseClaimsJws(jwtToken).getBody();
        System.out.println(abcd);
        //输出结果为:{jti=888, sub=小白, iat=1591518291, exp=1591520091}
    }
}

自定义claims
我们刚才的例子只是存储了id和subject两个信息,如果你想存储更多的信息(例如角色)可以定义自定义claims。创建测试类,并设置测试方法:

package com.sq.Demo;

import io.jsonwebtoken.*;

import java.util.Date;

public class Demo1_JWT {
    public static void main(String[] args) {

        long timeMillis = System.currentTimeMillis();
        timeMillis += 1800000L;
        Date date = new Date(timeMillis);

        JwtBuilder jwtBuilder = Jwts.builder()
                .setId("888") //设置唯一编号
                .setSubject("小白")   //设置主题,可以是JSON数据
                .setIssuedAt(new Date())//设置签发日期
                .setExpiration(date) //设置令牌30分钟后过期
                .claim("湖南", "长沙")      //.claim 方法可以自定义往JWT令牌里面设置自定义的内容
                .claim("湖北", "武汉")
                .signWith(SignatureAlgorithm.HS256, "abcd");//设置签名,使用HS256算法,地二个参数为密钥,暂时设置为abcd

        String jwtToken = jwtBuilder.compact(); //生成jwt令牌
        System.out.println(jwtToken);
        //输出结果为:eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1OTE1MTg3MTksImV4cCI6MTU5MTUyMDUxOCwi5rmW5Y2XIjoi6ZW_5rKZIiwi5rmW5YyXIjoi5q2m5rGJIn0.5GNAJFD56g3x4pgX-mxPWZZWnp7wzbh2AyAFII25eh4



       /* .setSigningKey("abcd") 设置签名密钥,必须要和生成的密钥一致
        .parseClaimsJws(jwtToken) 对jwt进行解析
        .getBody();//获取jwt令牌里内容*/
        Claims abcd = Jwts.parser().setSigningKey("abcd").parseClaimsJws(jwtToken).getBody();
        System.out.println(abcd);
        //输出结果为:{jti=888, sub=小白, iat=1591518719, exp=1591520518, 湖南=长沙, 湖北=武汉}
    }
}

玩jwt令牌里面设置自定义内容后可以发现jwt令牌的长度相比之前的要长

将jwt令牌鉴权集成到微服务中
JWT 实现微服务鉴权_第2张图片

1.  用户进入网关开始登陆,网关过滤器进行判断,如果是登录,则路由到后台管理微服务进
行登录
2. 用户登录成功,后台管理微服务签发JWT TOKEN信息返回给用户
3. 用户再次进入网关开始访问,网关过滤器接收用户携带的TOKEN 
4. 网关过滤器解析TOKEN ,判断是否有权限,如果有,则放行,如果没有则返回未认证错误

你可能感兴趣的:(加密,java)