JWT的详细使用

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 JWT的详细使用,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一、JWT

JWT概述

JSON Web Tokens 是一种开放的、行业标准的 RFC 7519方法,用于在两方之间安全地表示声明。它定义了一种简单的、自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公钥/私钥对来签名,防止被篡改。

JWT官网

一个JWT对象为一个很长的字符串,字符之间通过”.”分隔符分为三个子串。每一个子串表示了一个功能块,总共有以下三个部分:JWT头、有效载荷和签名

在这里插入图片描述

优缺点

优点:

1、jwt基于json,非常方便解析。

2、可以在令牌中自定义丰富的内容,易扩展。如:包含基本信息,如id、用户昵称、头像等信息,避免多次查询数据库

3、通过非对称加密算法及数字签名技术,JWT防止篡改,安全性高。

4、资源服务使用JWT可不依赖认证服务即可完成授权。

5、JWT不仅可用于认证,还可用于信息交换。

6、存储在客户端,不占用服务端的内存资源

缺点:

1、JWT令牌较长,占存储空间比较大。

2、服务器不保存会话状态,在使用期间不可能取消令牌或更改令牌的权限。即:一旦JWT签发,在有效期内将会一直有效。

3.、JWT本身包含认证信息,token是经过base64编码,所以可以解码,因此token加密前的对象不应该包含敏感信息,一旦信息泄露,任何人都可以获得令牌的所有权限。为了减少盗用,JWT的有效期不宜设置太长。

令牌结构

JWT令牌由三部分组成,每部分中间使用点(.)分隔,比如:xxx.yyy.zzz

头部(Header)

头部用于描述关于该JWT的最基本的信息,例如其令牌的类型(即JWT)以及签名所用的算法(如HMAC SHA256或RSA)

{
  "alg": "HS256",
  "typ": "JWT"
}
alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256)

typ属性表示令牌的类型,JWT令牌统一写为JWT

将上述JSON对象使用Base64Url编码,得到一个字符串就是JWT令牌的第一部分。

ewogICAgImFsZyI6ICJIUzI1NiIsCiAgICAidHlwIjogIkpXVCIKfQ==

载荷(playload)

第二部分是负载,内容也是一个json对象,它是存放有效信息的地方,它可以存放jwt提供的现成字段,比如:iss(签发者),exp(过期时间戳), sub(面向的用户)等,除默认字段外,还可以自定义私有字段。

此部分不建议存放敏感信息,因为此部分可以解码还原原始内容。

{
  "sub": "jwt_sub",
  "name": "jwt_name",
}

JWT指定七个默认字段供选择

iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT

将第二部分负载使用Base64Url编码,得到一个字符串就是JWT令牌的第二部分。

ewogICJzdWIiOiAiand0X3N1YiIsCiAgIm5hbWUiOiAiand0X25hbWUiLAp9

签证(signature)

第三部分是签名,此部分用于防止jwt内容被篡改。

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

首先是需要指定一个密码(secret),该密码仅保存在服务器中,并不向用户公开。使用标头中指定的签名算法(默认为HMAC SHA256)根据以下公式生成签名。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)
base64UrlEncode(header) :jwt令牌的第一部分。

base64UrlEncode(payload):jwt令牌的第二部分。

secret:签名所使用的密钥。

在计算出签名哈希后,JWT头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用”.”分隔,就构成整个JWT对象。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Base64URL算法

上述JWT头和有效载荷序列化的算法都用到了Base64 URL,该算法和常见Base64算法类似,但有一定区别。

作为令牌的JWT可以放在URL中,如api.baidu.com?token=xxx。

Base64中用的三个字符是+/=,由于在URL中有特殊含义,因此Base64 URL中做了替换,将=去掉,+-替换,/_替换,这就是Base64URL算法。

二、JJWT签发与验证token

JJWT是一个提供端到端的JWT创建和验证的Java库。

官方文档:https://github.com/jwtk/jjwt

引入依赖

<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

创建token

    public static void main(String[] args) {
        JwtBuilder builder = Jwts.builder()
                .setId(UUID.randomUUID().toString())   //设置唯一编号,token的ID
                .setSubject("sub_name")//设置主题,token中携带的数据,可以是JSON数据
                .setIssuedAt(new Date())//设置签发日期,即token的生成时间
                .signWith(SignatureAlgorithm.HS256, "SecretKey");//设置签名 使用HS256算法加密方式,并设置SecretKey(字符串)加密密码
        //构建并返回一个字符串
        System.out.println(builder.compact());
    }
eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhZjdlMjZjMi0yYzE1LTRhNjQtOWQ0ZS01MWE2YjQ4YmIzMDIiLCJzdWIiOiJzdWJfbmFtZSIsImlhdCI6MTYyMjI4MTkxOX0.vCIzHmQAA8f7bR8gJ9ag59gtR8zLNy3hAi5Gw0v697I

解析token

    public static void main(String[] args) {
        //jwt令牌
        String jwt="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhZjdlMjZjMi0yYzE1LTRhNjQtOWQ0ZS01MWE2YjQ4YmIzMDIiLCJzdWIiOiJzdWJfbmFtZSIsImlhdCI6MTYyMjI4MTkxOX0.vCIzHmQAA8f7bR8gJ9ag59gtR8zLNy3hAi5Gw0v697I";
        //解析令牌
        Claims claims = Jwts.parser().setSigningKey("SecretKey").parseClaimsJws(jwt).getBody();
        System.out.println(claims);
    }
{jti=af7e26c2-2c15-4a64-9d4e-51a6b48bb302, sub=sub_name, iat=1622281919}

如果token正确则正常解析,如果token不正确或者过期,则通过抛出的异常进行识别

try {
  		//.......
	    return BaseUtils.back(BaseUtils.OK,"success");
	}catch (ExpiredJwtException e){
	    return BaseUtils.back(BaseUtils.LOGIN_FAIL_OVERDUE,"登录过期,请重新登录!");
	}catch (UnsupportedJwtException e){
	    returnBaseUtils.back(BaseUtils.LOGIN_FAIL_NOT,"Tonken不合法!");
	}catch (Exception e){
	    return BaseUtils.back(BaseUtils.LOGIN_FAIL_NOT,"请重新登录!");
	}

设置过期时间

    public static void main(String[] args) {
        //过期时间:10s
        long ttl = 10 * 1000;
        //当前时间毫秒值
        long currentTimeMillis = System.currentTimeMillis();

        JwtBuilder builder = Jwts.builder()
                .setId(UUID.randomUUID().toString())   //设置唯一编号,token的ID
                .setSubject("sub_name")//设置主题,token中携带的数据,可以是JSON数据
                .setIssuedAt(new Date(currentTimeMillis))//设置签发日期,即token的生成时间
                .setExpiration(new Date(currentTimeMillis + ttl)) //设置过期时间
                .signWith(SignatureAlgorithm.HS256, "SecretKey");//设置签名 使用HS256算法加密方式,并设置SecretKey(字符串)加密密码
        //构建并返回一个字符串
        String jwt = builder.compact();
        System.out.println(jwt);
        try {
            Thread.sleep(3000);
            //Thread.sleep(10*1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //解析令牌
        Claims claims = Jwts.parser().setSigningKey("SecretKey").parseClaimsJws(jwt).getBody();
        System.out.println(claims);
    }

时间过期,则报错

Exception in thread "main" io.jsonwebtoken.ExpiredJwtException: JWT expired at 2021-05-29T18:05:53Z. Current time: 2021-05-29T18:05:58Z, a difference of 5509 milliseconds.  Allowed clock skew: 0 milliseconds.

自定义claims

如果需要存储更多的信息,可以使用自定义claims。
JwtBuilder builder = Jwts.builder()
                .setId(UUID.randomUUID().toString())   //设置唯一编号
                .setSubject("sub_name")//设置主题  可以是JSON数据
                .setIssuedAt(new Date(currentTimeMillis))//设置签发日期
                .setExpiration(new Date(currentTimeMillis + ttl)) //设置过期时间
                .claim("roles","{'role1','role2}") //如果需要存储更多的信息,可以使用自定义claims,如存放用户的角色权限信息
                .claim("name","小白白")
                .signWith(SignatureAlgorithm.HS256, "SecretKey");//设置签名 使用HS256算法,并设置SecretKey(字符串)
        //构建并返回一个字符串
        String jwt = builder.compact();
        System.out.println(jwt);
{jti=e25d97a4-bf08-4eab-aa64-a1bae09d4be5, sub=sub_name, iat=1622283121, exp=1622283131, roles={'role1','role2}, name=小白白}

三、拦截器校验Token

创建拦截器

@Component
public class CheckTokenInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String method = request.getMethod();
        //预请求放行
        if ("OPTIONS".equalsIgnoreCase(method)) {
            return true;
        }
        //头信息取出token
        String token = request.getHeader("token");
        if (token == null) {
            doResponse(response, BaseUtils.back(BaseUtils.LOGIN_FAIL_NOT, "请先登录!"));
        } else {
            try {
                JwtParser parser = Jwts.parser();
                //解析token的SigningKey必须和生成token时设置密码一致
                parser.setSigningKey("SecretKey"); 
                //如果token正确(密码正确,有效期内)则正常执行,否则抛出异常
                Jws<Claims> claimsJws = parser.parseClaimsJws(token);
                return true;
            } catch (ExpiredJwtException e) {
                doResponse(response, BaseUtils.back(BaseUtils.LOGIN_FAIL_OVERDUE, "登录过期,请重新登录!"));
            } catch (UnsupportedJwtException e) {
                doResponse(response, BaseUtils.back(BaseUtils.LOGIN_FAIL_NOT, "Token不合法!"));
            } catch (Exception e) {
                doResponse(response, BaseUtils.back(BaseUtils.LOGIN_FAIL_NOT, "请先登录!"));
            }
        }
        return false;
    }

    private void doResponse(HttpServletResponse response, ResultVO resultVO) throws IOException {
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        String s = new ObjectMapper().writeValueAsString(resultVO);
        out.print(s);
        out.flush();
        out.close();
    }
}

配置拦截器

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Autowired
    private CheckTokenInterceptor checkTokenInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(checkTokenInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/index");
    }
}

请求头传递token

axios({
    url:"http://localhost:8888/user/login",
    method:"post",
    params:{
        username:"admin",
        password:"admin"
    },
    headers:{
       token:this.token
    },
}).then(function(res){
    console.log(res)
});

四、生成私钥和公钥

生成密钥

该命令生成密钥证书,采用RSA 算法每个证书包含公钥和私钥

keytool -genkeypair -alias aliaskey -keyalg RSA -keypass adminkey -keystore ybzy.jks -storepass adminkeystore

Keytool 是一个java提供的证书管理工具 , 只要有安装JDK环境即可使用

-alias:密钥的别名
-keyalg:使用的hash算法
-keypass:密钥的访问密码
-keystore:密钥库文件名,ybzy.jks保存了生成的证书
-storepass:密钥库的访问密码
D:\>keytool -genkeypair -alias aliaskey -keyalg RSA -keypass adminkey -keystore ybzy.jks  -storepass adminkeystore
您的名字与姓氏是什么?
  [Unknown]:  test
您的组织单位名称是什么?
  [Unknown]:  ybzy
您的组织名称是什么?
  [Unknown]:  您所在的城市或区域名称是什么?
  [Unknown]:
D:\>keytool -genkeypair -alias aliaskey -keyalg RSA -keypass adminkey -keystore ybzy.jks  -storepass adminkeystore
您的名字与姓氏是什么?
  [Unknown]:  test
您的组织单位名称是什么?
  [Unknown]:  ybzy
您的组织名称是什么?
  [Unknown]:  jwt
您所在的城市或区域名称是什么?
  [Unknown]:  sc
您所在的省//自治区名称是什么?
  [Unknown]:  cd
该单位的双字母国家/地区代码是什么?
  [Unknown]:  cn
CN=test, OU=ybzy, O=jwt, L=sc, ST=cd, C=cn是否正确?
  []:  y


Warning:
JKS 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore ybzy.jks -destkeystore ybzy.jks -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。

D:\>

查询证书信息

keytool -list -keystore ybzy.jks
D:\>keytool -list -keystore ybzy.jks
输入密钥库口令:
密钥库类型: jks
密钥库提供方: SUN

您的密钥库包含 1 个条目

aliaskey, 2021-1-30, PrivateKeyEntry,
证书指纹 (SHA-256): 64:4B:67:5A:F2:B7:33:15:35:DC:B9:CD:98:CF:A8:D0:7E:DF:3F:47:17:3A:04:ED:6E:2A:0B:75:65:2D:BC:F7

Warning:
JKS 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore ybzy.jks -destkeystore ybzy.jks -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。

D:\>

删除别名

keytool -delete -alias aliaskey -keystore ybzy.jks

导出公钥

openssl是一个加解密工具包,使用openssl来导出公钥信息。

安装并配置openssl的path环境变量,在ybzy.jks文件所在目录执行命令:
keytool -list -rfc --keystore ybzy.jks| openssl x509 -inform pem -pubkey
D:\>keytool -list -rfc --keystore ybzy.jks| openssl x509 -inform pem -pubkey
输入密钥库口令:

*****************  WARNING WARNING WARNING  *****************
* 存储在您的密钥库中的信息的完整性  *
* 尚未经过验证!  为了验证其完整性, *
* 必须提供密钥库口令。                  *
*****************  WARNING WARNING WARNING  *****************

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlyu4kW0k9+du8mJuiMqs
B668fExfrxCU8phM6+/tefXbgwNFZ6xgGviC5c1O+DlN+ByBI3kMpVMotSN5Un4i
zdRI9DgHSjCx9jEazwsEzSEnCpDR3A2upQlm3Pdm59c13bDsHetqk57Pp16SLalp
FW1+ET79aTdBzv9Tn3a8Dm2omvE/CftbV48FC/1DZ+0X00dlUpPANrqFtqAV/2ad
CnbdDPtctblN3zMlZKIEjUArRfWctpM5mFYzg7r0Uy+GJwOYUbTUPo0ZeVnDWV98
IyyktVwEnjYPWS0ii9wiXMdQFJl5EMlmA3l3jpmnqyWwpBtb+JohKc0pPwDPeFaD
bQIDAQAB
-----END PUBLIC KEY-----
-----BEGIN CERTIFICATE-----

Warning:MIIDRTCCAi2gAwIBAgIEDB+FvDANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJj
bjELMAkGA1UECBMCY2QxCzAJBgNVBAcTAnNjMQ0wCwYDVQQKEwR5Ynp5MQwwCgYD
VQQLEwNqd3QxDTALBgNVBAMTBHRlc3QwHhcNMjEwMTMwMDUzMDA3WhcNMjEwNDMw
MDUzMDA3WjBTMQswCQYDVQQGEwJjbjELMAkGA1UECBMCY2QxCzAJBgNVBAcTAnNj
MQ0wCwYDVQQKEwR5Ynp5MQwwCgYDVQQLEwNqd3QxDTALBgNVBAMTBHRlc3QwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCXK7iRbST3527yYm6IyqwHrrx8
TF+vEJTymEzr7+159duDA0VnrGAa+ILlzU74OU34HIEjeQylUyi1I3lSfiLN1Ej0
OAdKMLH2MRrPCwTNIScKkNHcDa6lCWbc92bn1zXdsOwd62qTns+nXpItqWkVbX4R
Pv1pN0HO/1OfdrwObaia8T8J+1tXjwUL/UNn7RfTR2VSk8A2uoW2oBX/Zp0Kdt0M
+1y1uU3fMyVkogSNQCtF9Zy2kzmYVjODuvRTL4YnA5hRtNQ+jRl5WcNZX3wjLKS1
XASeNg9ZLSKL3CJcx1AUmXkQyWYDeXeOmaerJbCkG1v4miEpzSk/AM94VoNtAgMB
AAGjITAfMB0GA1UdDgQWBBQ39bf9PfWzwxaVM4FOy49jcG5cfzANBgkqhkiG9w0B
AQsFAAOCAQEAPp8C9M1vkNBfeNFEl+EC+X7MC650LSYsjWoHPvVw0hENWkl9WN8W
prgDTmbxLvZUPT5z/sWluqTTkPbZXSUrrgToYA3s5hKeyZe8eOn+YKbstCt2qgCv
Rlaqe76uB0OIO8H/j4Vsk1Hu3rasTpxYJkyTriGkoFt6LmN4s0GBifuKeAKcBHLD
ICsOYv3TMvVzTHG/6YiZGCA4OjSVTIBHgp3HL20f/Mnfx4qxOik1JC5squuzeIwh
MofA5fxUlBNwxdd4W9aadfpa11C6rYq1+g2SDMB8YimvXNmijwDRxrrWXDXDj4gI
jByQRtpIx7d5VyNC6mf8F6yYx9IrgXuvGA==
-----END CERTIFICATE-----

JKS 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore ybzy.jks -destkeystore ybzy.jks -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。

D:\>

将公钥拷贝到文本文件中,合并为一行。

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlyu4kW0k9+du8mJuiMqs
B668fExfrxCU8phM6+/tefXbgwNFZ6xgGviC5c1O+DlN+ByBI3kMpVMotSN5Un4i
zdRI9DgHSjCx9jEazwsEzSEnCpDR3A2upQlm3Pdm59c13bDsHetqk57Pp16SLalp
FW1+ET79aTdBzv9Tn3a8Dm2omvE/CftbV48FC/1DZ+0X00dlUpPANrqFtqAV/2ad
CnbdDPtctblN3zMlZKIEjUArRfWctpM5mFYzg7r0Uy+GJwOYUbTUPo0ZeVnDWV98
IyyktVwEnjYPWS0ii9wiXMdQFJl5EMlmA3l3jpmnqyWwpBtb+JohKc0pPwDPeFaD
bQIDAQAB
-----END PUBLIC KEY-----

五、JWT结合私钥和公钥的使用

	    <dependency>
	            <groupId>com.alibaba</groupId>
	            <artifactId>fastjson</artifactId>
	            <version>1.2.76</version>
	      </dependency>
	        
	     <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
            <version>2.2.4.RELEASE</version>
        </dependency>

私钥生成jwt令牌

    @Test
    public void createJwtTest() {
        //密钥库文件
        String keystore = "ybzy.jks";
        //密钥库的密码
        String keystore_password = "adminkeystore";

        //密钥库文件路径
        ClassPathResource classPathResource = new ClassPathResource(keystore);
        //密钥别名
        String alias = "aliaskey";
        //密钥的访问密码此密码和别名要匹配
        String key_password = "adminkey";
        //密钥工厂
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(classPathResource, keystore_password.toCharArray());
        //密钥对(公钥和私钥)
        KeyPair keyPair = keyStoreKeyFactory.getKeyPair(alias, key_password.toCharArray());
        //获取私钥
        RSAPrivateKey aPrivate = (RSAPrivateKey) keyPair.getPrivate();
        //定义payload信息 jwt令牌的内容
        Map<String, String> body = new HashMap<>();
        body.put("name", "jwt");
        String bodyString = JSON.toJSONString(body);
        //生成jwt令牌
        Jwt jwt = JwtHelper.encode(bodyString, new RsaSigner(aPrivate));
        //取出jwt令牌
        String encoded = jwt.getEncoded();
        System.out.println(encoded);
    }

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiand0In0.iGmIVrHO243Jd46IbZDdQXhEm0I3d1Qlb_P1raHE7ys7G5pc9p8GZZv5B3yumSDg8NvmVD9AzUglnT_PJU1_bz0W5b4F5ZHaF1IiDFyqdopka_dOqrO0DO4v26NrBQeUwGCOh37hcBVSmgFDIYUK0dLw_Mi2oovEEpSt0uYkRGO9ctur0kJngFiXX5WtTg0IIzyDKFpFsgTEaz15Pb1xFmlkM7pZ0h0Lh6QQEhr9WdO5ZPSavZMCd02j3N6VGWDcZgxLFKv2BhMYzmoQtMIISI1ZN0I5kCP1yGuOwT0RboJlU1vtcnqlVyigvIFITmebSZGmGqpUgprRDXof2g

公钥解析jwt令牌

    @Test
    public void testVerify() {
        //公钥
        String publickey = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlyu4kW0k9+du8mJuiMqsB668fExfrxCU8phM6+/tefXbgwNFZ6xgGviC5c1O+DlN+ByBI3kMpVMotSN5Un4izdRI9DgHSjCx9jEazwsEzSEnCpDR3A2upQlm3Pdm59c13bDsHetqk57Pp16SLalpFW1+ET79aTdBzv9Tn3a8Dm2omvE/CftbV48FC/1DZ+0X00dlUpPANrqFtqAV/2adCnbdDPtctblN3zMlZKIEjUArRfWctpM5mFYzg7r0Uy+GJwOYUbTUPo0ZeVnDWV98IyyktVwEnjYPWS0ii9wiXMdQFJl5EMlmA3l3jpmnqyWwpBtb+JohKc0pPwDPeFaDbQIDAQAB-----END PUBLIC KEY-----";
        //jwt令牌
        String jwtString = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiand0In0.iGmIVrHO24-3Jd46IbZDdQXhEm0I3d1Qlb_P1raHE7ys7G5pc9p8GZZv5B3yumSDg8NvmVD9AzUglnT_PJU1_bz-0W5b4F5ZHaF1-IiDFyqdopka_dOqrO0DO4v26NrBQeUwGCOh37hcBVSmgFDIYUK0dLw_Mi2oovEEpSt0uYkRGO9ctur0kJngFiXX5WtTg0IIzyDKFpFsgTEaz15Pb1xFmlkM7pZ0h0-Lh6QQEhr9WdO5ZPSavZMCd02j3N6VGWDcZgxLFKv2BhMYzmoQtMIISI1ZN0I5kCP1yGuOwT0RboJlU1vtcnqlVyigvIFITmebSZGmGqpUgprRDXof2g";
        //校验jwt令牌
        Jwt jwt = JwtHelper.decodeAndVerify(jwtString, new RsaVerifier(publickey));
        //获取jwt原始内容
        String claims = jwt.getClaims();
        System.out.println(claims);
    }
}
{"name":"jwt"}

六、JWT工具类

public class JwtUtils {

	// token过期时间
    public static final long EXPIRE = 1000 * 60 * 60 * 24; 
    
     // 秘钥
    public static final String APP_SECRET = "ukc8BSUzI1NiIsInR5cCI6Ikus2jZWLHO2";

    //生成token字符串的方法
    public static String getJwtToken(String id, String nickname){

        String JwtToken = Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")

                .setSubject("user")
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))

                .claim("id", id)  //设置token主体部分 ,存储用户信息
                .claim("nickname", nickname)

                .signWith(SignatureAlgorithm.HS256, APP_SECRET)
                .compact();

        return JwtToken;
    }

    /**
     * 判断token是否存在与有效
     */
    public static boolean checkToken(String jwtToken) {
        if(StringUtils.isEmpty(jwtToken)) return false;
        try {
            Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 判断token是否存在与有效
     */
    public static boolean checkToken(HttpServletRequest request) {
        try {
            String jwtToken = request.getHeader("token");
            if(StringUtils.isEmpty(jwtToken)) return false;
            Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 根据token字符串获取user的id
     */
    public static String getMemberIdByJwtToken(HttpServletRequest request) {
        String jwtToken = request.getHeader("token");
        if(StringUtils.isEmpty(jwtToken)) return "";
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        Claims claims = claimsJws.getBody();
        return (String)claims.get("id");
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/137049.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!