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