?目录
?一、jwt出现的原因及工作原理?
1. JWT是什么
2. 为什么使用JWT
3. JWT的工作原理
4、jwt解决不需要登录就能直接访问的问题:?
解决登录后树形菜单未出现的问题?:
二、jwt工具类介绍,三种场景
1、jwt工具类
2、三种场景
三、jwt与vuex配合在SPA项目中的应用
目标:
①、jwt出现的原因及工作原理 ②、jwt工具类介绍,三种场景 ③、jwt与vuex配合在SPA项目中的应用
?一、jwt出现的原因及工作原理?
1. JWT是什么
JSON Web Token (JWT),它是目前最流行的跨域身份验证解决方案
2. 为什么使用JWT
JWT的精髓在于:“去中心化”,数据是保存在客户端的。
3. JWT的工作原理
? ?①. 是在服务器身份验证之后,将生成一个JSON对象并将其发送回用户,示例如下: ? ? ? {"UserName": "Chongchong","Role": "Admin","Expire": "2018-08-08 20:15:56"}
? ?②. 之后,当用户与服务器通信时,客户在请求中发回JSON对象 ? ?? ? ?③. 为了防止用户篡改数据,服务器将在生成对象时添加签名,并对发回的数据进行验证
传统开发对资源的访问限制利用session完成图解:
jwt所解决的问题及机制:
4、jwt解决不需要登录就能直接访问的问题:?
不需要登录就能直接访问(不合理):
①、web.xml:解决jwt问题的过滤器
<!-- 解决jwt问题的过滤器 --> ?? ?<filter> ?? ??? ?<filter-name>jwtFilter</filter-name> ?? ??? ?<filter-class>com.zking.vue.util.JwtFilter</filter-class> ?? ?</filter> ?? ?<filter-mapping> ?? ??? ?<filter-name>jwtFilter</filter-name> ?? ??? ?<url-pattern>/*</url-pattern> ?? ?</filter-mapping>
②、JwtFilter.java:开启jwt令牌验证功能
package com.zking.vue.util;
import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern;
import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import io.jsonwebtoken.Claims;
/**se ?* * JWT验证过滤器,配置顺序 :CorsFilte-->JwtFilter-->struts2中央控制器 ?*? ?* @author Administrator ?* ?*/ public class JwtFilter implements Filter {
?? ?// 排除的URL,一般为登陆的URL(请改成自己登陆的URL) ?? ?private static String EXCLUDE = "^/vue/userAction_login\\.action?.*$";
?? ?private static Pattern PATTERN = Pattern.compile(EXCLUDE);
?? ?//private boolean OFF = true;// true关闭jwt令牌验证功能 ?? ?private boolean OFF = false;
?? ?@Override ?? ?public void init(FilterConfig filterConfig) throws ServletException { ?? ?}
?? ?@Override ?? ?public void destroy() { ?? ?}
?? ?@Override ?? ?public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) ?? ??? ??? ?throws IOException, ServletException { ?? ??? ?HttpServletRequest req = (HttpServletRequest) request; ?? ??? ?HttpServletResponse resp = (HttpServletResponse) response; ?? ??? ?String path = req.getServletPath(); ?? ??? ?if (OFF || isExcludeUrl(path)) {// 登陆直接放行 ?? ??? ??? ?chain.doFilter(request, response); ?? ??? ??? ?return; ?? ??? ?}
?? ??? ?// 从客户端请求头中获得令牌并验证 ?? ??? ?String jwt = req.getHeader(JwtUtils.JWT_HEADER_KEY); ?? ??? ?Claims claims = this.validateJwtToken(jwt); ?? ??? ?if (null == claims) { ?? ??? ??? ?// resp.setCharacterEncoding("UTF-8"); ?? ??? ??? ?resp.sendError(403, "JWT令牌已过期或已失效"); ?? ??? ??? ?return; ?? ??? ?} else { ?? ??? ??? ?String newJwt = JwtUtils.copyJwt(jwt, JwtUtils.JWT_WEB_TTL); ?? ??? ??? ?resp.setHeader(JwtUtils.JWT_HEADER_KEY, newJwt); ?? ??? ??? ?chain.doFilter(request, response); ?? ??? ?} ?? ?}
?? ?/** ?? ? * 验证jwt令牌,验证通过返回声明(包括公有和私有),返回null则表示验证失败 ?? ? */ ?? ?private Claims validateJwtToken(String jwt) { ?? ??? ?Claims claims = null; ?? ??? ?try { ?? ??? ??? ?if (null != jwt) { ?? ??? ??? ??? ?claims = JwtUtils.parseJwt(jwt); ?? ??? ??? ?} ?? ??? ?} catch (Exception e) { ?? ??? ??? ?e.printStackTrace(); ?? ??? ?} ?? ??? ?return claims; ?? ?}
?? ?/** ?? ? * 是否为排除的URL ?? ? *? ?? ? * @param path ?? ? * @return ?? ? */ ?? ?private boolean isExcludeUrl(String path) { ?? ??? ?Matcher matcher = PATTERN.matcher(path); ?? ??? ?return matcher.matches(); ?? ?}
?? ?// public static void main(String[] args) { ?? ?// String path = "/sys/userAction_doLogin.action?username=zs&password=123"; ?? ?// Matcher matcher = PATTERN.matcher(path); ?? ?// boolean b = matcher.matches(); ?? ?// System.out.println(b); ?? ?// }
}
③、UserAction .java:将jwt令牌塞入响应头
package com.zking.vue.web;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.opensymphony.xwork2.ModelDriven;
import com.zking.base.web.BaseAction;
import com.zking.vue.biz.UserBiz;
import com.zking.vue.entity.User;
import com.zking.vue.util.JsonData;
import com.zking.vue.util.JwtUtils;
import com.zking.vue.util.PageBean;
import com.zking.vue.util.ResponseUtil;
import com.zking.vue.util.StringUtils;
public class UserAction extends BaseAction implements ModelDriven<User>{
private UserBiz userBiz;
private User user = new User();
public UserBiz getUserBiz() {
return userBiz;
}
public void setUserBiz(UserBiz userBiz) {
this.userBiz = userBiz;
}
public String login() {
ObjectMapper om = new ObjectMapper();
JsonData jsonData = null;
try {
if(StringUtils.isBlank(user.getUname()) || StringUtils.isBlank(user.getPwd())) {
jsonData = new JsonData(0, "用户或者密码为空", user);
}else {
User u = this.userBiz.login(user);
Map<String, Object> claims = new HashMap<String, Object>();
claims.put("uname",user.getUname());
claims.put("pwd", user.getPwd());
String jwt = JwtUtils.createJwt(claims, JwtUtils.JWT_WEB_TTL);
response.setHeader(JwtUtils.JWT_HEADER_KEY, jwt);
jsonData = new JsonData(1, "登录成功", u);
}
} catch (Exception e) {
e.printStackTrace();
jsonData = new JsonData(0, "用户或者密码错误", user);
}finally {
try {
ResponseUtil.write(response, om.writeValueAsString(jsonData));
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
public String getAsyncData() {
ObjectMapper om = new ObjectMapper();
try {
Thread.sleep(6000);
ResponseUtil.write(response, om.writeValueAsString("http://www.javaxl.com"));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public User getModel() {
return user;
}
}
④、界面展示
因为没有登录,所有看不到左侧树形菜单?
?并且报出403错误
403错误出现的原因:
? ? ? ? ①被限制了,限制了访问,没有拿到凭证;
? ? ? ? ②做爬虫的时候也会出现,IP被封了,没有凭证;
? ? ? ? ③被拉入黑名单了;
解决登录后树形菜单未出现的问题?:
①、jwt令牌:
②、jwt令牌响应头在浏览器中,前端代码并未获得
http.js?拿到所有的响应头信息
/** ?* vue项目对axios的全局配置 ?*/ import axios from 'axios' import qs from 'qs' //引入action模块,并添加至axios的类属性urls上 import action from '@/api/action' axios.urls = action // axios默认配置 axios.defaults.timeout = 10000; // 超时时间 // axios.defaults.baseURL = 'http://localhost:8080/j2ee15'; // 默认地址 axios.defaults.baseURL = action.SERVER; //整理数据 // 只适用于 POST,PUT,PATCH,transformRequest` 允许在向服务器发送前,修改请求数据 axios.defaults.transformRequest = function(data) { ?? ?data = qs.stringify(data); ?? ?return data; }; // 请求拦截器 axios.interceptors.request.use(function(config) { ?? ?// var jwt = window.vm.$store.getters.getJwt; ?? ?// config.headers['jwt'] = jwt; ?? ?return config; }, function(error) { ?? ?return Promise.reject(error); }); // 响应拦截器 axios.interceptors.response.use(function(response) { ?? ?//debugger; ? /* 拿到所有的响应头信息*/ ?? ?var jwt = response.headers['jwt']; ?? ?if(jwt){?// 通过mutations进行值得设置 ?? ??? ?window.vm.$store.commit('setJwt',{jwt:jwt}); ?? ?} ?? ?return response; }, function(error) { ?? ?return Promise.reject(error); }); // // 路由请求拦截 // // http request 拦截器 // axios.interceptors.request.use( // ?? ?config => { // ?? ??? ?//config.data = JSON.stringify(config.data); // ?? ??? ?//config.headers['Content-Type'] = 'application/json;charset=UTF-8'; // ?? ??? ?//config.headers['Token'] = 'abcxyz'; // ?? ??? ?//判断是否存在ticket,如果存在的话,则每个http header都加上ticket // ?? ??? ?// if (cookie.get("token")) { // ?? ??? ?// ?? ?//用户每次操作,都将cookie设置成2小时 // ?? ??? ?// ?? ?cookie.set("token", cookie.get("token"), 1 / 12) // ?? ??? ?// ?? ?cookie.set("name", cookie.get("name"), 1 / 12) // ?? ??? ?// ?? ?config.headers.token = cookie.get("token"); // ?? ??? ?// ?? ?config.headers.name = cookie.get("name"); // ?? ??? ?// } // ?? ??? ?return config; // ?? ?}, // ?? ?error => { // ?? ??? ?return Promise.reject(error.response); // ?? ?});
// // 路由响应拦截 // // http response 拦截器 // axios.interceptors.response.use( // ?? ?response => { // ?? ??? ?if (response.data.resultCode == "404") { // ?? ??? ??? ?console.log("response.data.resultCode是404") // ?? ??? ??? ?// 返回 错误代码-1 清除ticket信息并跳转到登录页面 // ?? ??? ??? ?// ? ? ?cookie.del("ticket") // ?? ??? ??? ?// ? ? ?window.location.href='http://login.com' // ?? ??? ??? ?return // ?? ??? ?} else { // ?? ??? ??? ?return response; // ?? ??? ?} // ?? ?}, // ?? ?error => { // ?? ??? ?return Promise.reject(error.response) // 返回接口返回的错误信息 // ?? ?}); export default axios;
③、将jwt令牌的值放到vuex里面去
通过mutations.js进行值得设置,写setJwt方法;
this关键字只能在vue组件里面出现,在js中要调用vuex的功能window.vm(vm是随便取的名字)代表了this
export default{ ? setResturantName:(state,payload)=>{ ? ? state.resturantName=payload.resturantName; ? }, ? setJwt:(state,payload)=>{ ? ? state.jwt=payload.jwt; ? }, ? doAjax:(state,payload)=>{ ? ? // 需求:想在当前文件中与后台服务器做数据交互 ? ? let _this=payload._this; ? ? let url = _this.axios.urls.SYSTEM_MENU_TREE; ? ? _this.axios.post(url, {}).then((resp) => { ? ? ? console.log(resp); ? ? }).catch(function(error) { ? ? ? console.log(error); ? ? });
? } }
④、State.js添加jwt变量
export default { ? resturantName: 'XXX餐馆', ? jwt: '' }
⑤、main.js中给window.vm赋值
⑥、 第二次请求的时候将jwt的值带到请求头里面去
放开http.js请求拦截器
// 请求拦截器 axios.interceptors.request.use(function(config) { ?? ?var jwt = window.vm.$store.getters.getJwt; ?? ?config.headers['jwt'] = jwt; ?? ?return config; }, function(error) { ?? ?return Promise.reject(error); });
⑦、Getters.js中定义获取的方法
export default{ ? getResturantName:(state)=>{ ? ? return state.resturantName; ? }, ? getJwt:(state)=>{ ? ? return state.jwt; ? } }
⑧、界面展示
login.action把jwt在响应头出现,登录请求中没有jwt;
第二次访问首页里面的信息,响应中出现jwt;
第二次请求会把第一次登录后的令牌携带到后端服务器中,作为凭证
问题:
在同一个浏览器中,登录进入首页后,
再次打开一个界面复制首页链接打开首页,访问不到首页,
原因:
第一次请求头中没有jwt,然后请求后台服务器生成了一个jwt返回回来,此时响应头中就要jwt了,
第二次访问请求头中有jwt,是把第一次的响应头拿到的第二次来用,返回回去,请求的时候又带回来了,每一次请求都是上一次的,
当从新开一个界面是,请求头中没有jwt,因此访问不到;
所有说;jwt的安全性比session高,
二、jwt工具类介绍,三种场景
1、jwt工具类
①、jwt令牌包含:
有效载荷:就是用户信息
?签名:就是密码本
有效载荷就是看不懂的字符串,要想看懂有效载荷就得用签名
②、jwtUtils.java
parseJwt方法:解析看不懂的字符串变成看的懂得用户信息;
createJwt方法:把用户信息变成一个看不懂的字符串;
package com.zking.vue.util; import java.util.Date; import java.util.Map; import java.util.UUID; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; /** ?* JWT验证过滤器:配置顺序 CorsFilte->JwtUtilsr-->StrutsPrepareAndExecuteFilter ?* ?*/ public class JwtUtils { ?? ?/** ?? ? * JWT_WEB_TTL:WEBAPP应用中token的有效时间,默认30分钟 ?? ? */ ?? ?public static final long JWT_WEB_TTL = 30 * 60 * 1000;
?? ?/** ?? ? * 将jwt令牌保存到header中的key ?? ? */ ?? ?public static final String JWT_HEADER_KEY = "jwt"; ?? ?// 指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。 ?? ?private static final SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS256; ?? ?private static final String JWT_SECRET = "f356cdce935c42328ad2001d7e9552a3";// JWT密匙 ?? ?private static final SecretKey JWT_KEY;// 使用JWT密匙生成的加密key
?? ?static { ?? ??? ?byte[] encodedKey = Base64.decodeBase64(JWT_SECRET); ?? ??? ?JWT_KEY = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES"); ?? ?} ?? ?private JwtUtils() { ?? ?} ?? ?/** ?? ? * 解密jwt,获得所有声明(包括标准和私有声明) ?? ? *? ?? ? * @param jwt ?? ? * @return ?? ? * @throws Exception ?? ? */ ?? ?public static Claims parseJwt(String jwt) { ?? ??? ?Claims claims = Jwts.parser().setSigningKey(JWT_KEY).parseClaimsJws(jwt).getBody(); ?? ??? ?return claims; ?? ?} ?? ?/** ?? ? * 创建JWT令牌,签发时间为当前时间 ?? ? *? ?? ? * @param claims ?? ? * ? ? ? ? ? ?创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的) ?? ? * @param ttlMillis ?? ? * ? ? ? ? ? ?JWT的有效时间(单位毫秒),当前时间+有效时间=过期时间 ?? ? * @return jwt令牌 ?? ? */ ?? ?public static String createJwt(Map<String, Object> claims, long ttlMillis) { ?? ??? ?// 生成JWT的时间,即签发时间 ?? ??? ?long nowMillis = System.currentTimeMillis();
?? ??? ?// 下面就是在为payload添加各种标准声明和私有声明了 ?? ??? ?// 这里其实就是new一个JwtBuilder,设置jwt的body ?? ??? ?JwtBuilder builder = Jwts.builder() ?? ??? ??? ??? ?// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的 ?? ??? ??? ??? ?.setClaims(claims) ?? ??? ??? ??? ?// 设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。 ?? ??? ??? ??? ?// 可以在未登陆前作为身份标识使用 ?? ??? ??? ??? ?.setId(UUID.randomUUID().toString().replace("-", "")) ?? ??? ??? ??? ?// iss(Issuser)签发者,写死 ?? ??? ??? ??? ?// .setIssuer("zking") ?? ??? ??? ??? ?// iat: jwt的签发时间 ?? ??? ??? ??? ?.setIssuedAt(new Date(nowMillis)) ?? ??? ??? ??? ?// 代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可放数据{"uid":"zs"}。此处没放 ?? ??? ??? ??? ?// .setSubject("{}") ?? ??? ??? ??? ?// 设置签名使用的签名算法和签名使用的秘钥 ?? ??? ??? ??? ?.signWith(SIGNATURE_ALGORITHM, JWT_KEY) ?? ??? ??? ??? ?// 设置JWT的过期时间 ?? ??? ??? ??? ?.setExpiration(new Date(nowMillis + ttlMillis));
?? ??? ?return builder.compact(); ?? ?} ?? ?/** ?? ? * 复制jwt,并重新设置签发时间(为当前时间)和失效时间 ?? ? *? ?? ? * @param jwt ?? ? * ? ? ? ? ? ?被复制的jwt令牌 ?? ? * @param ttlMillis ?? ? * ? ? ? ? ? ?jwt的有效时间(单位毫秒),当前时间+有效时间=过期时间 ?? ? * @return ?? ? */ ?? ?public static String copyJwt(String jwt, Long ttlMillis) { ?? ??? ?Claims claims = parseJwt(jwt); ?? ??? ?// 生成JWT的时间,即签发时间 ?? ??? ?long nowMillis = System.currentTimeMillis(); ?? ??? ?// 下面就是在为payload添加各种标准声明和私有声明了 ?? ??? ?// 这里其实就是new一个JwtBuilder,设置jwt的body ?? ??? ?JwtBuilder builder = Jwts.builder() ?? ??? ??? ??? ?// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的 ?? ??? ??? ??? ?.setClaims(claims) ?? ??? ??? ??? ?// 设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。 ?? ??? ??? ??? ?// 可以在未登陆前作为身份标识使用 ?? ??? ??? ??? ?//.setId(UUID.randomUUID().toString().replace("-", "")) ?? ??? ??? ??? ?// iss(Issuser)签发者,写死 ?? ??? ??? ??? ?// .setIssuer("zking") ?? ??? ??? ??? ?// iat: jwt的签发时间 ?? ??? ??? ??? ?.setIssuedAt(new Date(nowMillis)) ?? ??? ??? ??? ?// 代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串,可放数据{"uid":"zs"}。此处没放 ?? ??? ??? ??? ?// .setSubject("{}") ?? ??? ??? ??? ?// 设置签名使用的签名算法和签名使用的秘钥 ?? ??? ??? ??? ?.signWith(SIGNATURE_ALGORITHM, JWT_KEY) ?? ??? ??? ??? ?// 设置JWT的过期时间 ?? ??? ??? ??? ?.setExpiration(new Date(nowMillis + ttlMillis)); ?? ??? ?return builder.compact(); ?? ?} }
2、三种场景
①、三种场景及结果展示
第一个:是怎么通过jwt工具类去生成jwt令牌和解析jwt令牌;
用户信息都获得了,签发过期时间都出现了,
第二个:jwt令牌过期场景
以下错误就是令牌过期:
第三个:延续令牌的存活时间
令牌过期时间为30分钟,假如一直在使用,30分钟后就要过期(不合理),
因此,需要设置最后使用时间为签发时间,再过30分钟为过期时间
解决方法:copy? jwt令牌,从新设置签发过期时间
②、相关代码
package com.zking.vue.test;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import com.zking.vue.util.JwtUtils;
import io.jsonwebtoken.Claims;
public class JwtDemo {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
@Test
public void test1() {// 生成JWT
Map<String, Object> claims = new HashMap<String, Object>();
claims.put("username", "zss");
claims.put("age", 18);
String jwt = JwtUtils.createJwt(claims, JwtUtils.JWT_WEB_TTL);
System.out.println(jwt);
Claims parseJwt = JwtUtils.parseJwt(jwt);
for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
Date d1 = parseJwt.getIssuedAt();
Date d2 = parseJwt.getExpiration();
System.out.println("令牌签发时间:" + sdf.format(d1));
System.out.println("令牌过期时间:" + sdf.format(d2));
}
@Test
public void test2() {// 解析oldJwt
// String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjI5MDMzNjAsImlhdCI6MTU2MjkwMTU2MCwiYWdlIjoxOCwianRpIjoiZDVjMzE4Njg0MDcyNDgyZDg1MDE5ODVmMDY3OGQ4NjkiLCJ1c2VybmFtZSI6InpzcyJ9.XDDDRRq5jYq5EdEBHtPm7GcuBz4S0VhDTS1amRCdf48";
String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjM1MjU5MjMsImlhdCI6MTU2MzUyNDEyMywiYWdlIjoxOCwianRpIjoiOTAzNmMwY2Q3NGIwNDBjMzgzMDAxYzdiNmZkMzYzZmIiLCJ1c2VybmFtZSI6InpzcyJ9.sgV9fr4fgmmahDFRJnsfazA6R3H-gNMVcg2ucA227n4";
Claims parseJwt = JwtUtils.parseJwt(oldJwt);
for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
Date d1 = parseJwt.getIssuedAt();
Date d2 = parseJwt.getExpiration();
System.out.println("令牌签发时间:" + sdf.format(d1));
System.out.println("令牌过期时间:" + sdf.format(d2));
}
@Test
public void test3() {// 复制jwt,并延时30秒
String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjI5MDMzNjAsImlhdCI6MTU2MjkwMTU2MCwiYWdlIjoxOCwianRpIjoiZDVjMzE4Njg0MDcyNDgyZDg1MDE5ODVmMDY3OGQ4NjkiLCJ1c2VybmFtZSI6InpzcyJ9.XDDDRRq5jYq5EdEBHtPm7GcuBz4S0VhDTS1amRCdf48";
String jwt = JwtUtils.copyJwt(oldJwt, JwtUtils.JWT_WEB_TTL);
Claims parseJwt = JwtUtils.parseJwt(jwt);
for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
Date d1 = parseJwt.getIssuedAt();
Date d2 = parseJwt.getExpiration();
System.out.println("令牌签发时间:" + sdf.format(d1));
System.out.println("令牌过期时间:" + sdf.format(d2));
}
@Test
public void test4() {// 测试JWT的有效时间
Map<String, Object> claims = new HashMap<String, Object>();
claims.put("username", "zss");
String jwt = JwtUtils.createJwt(claims, 3 * 1000L);
System.out.println(jwt);
Claims parseJwt = JwtUtils.parseJwt(jwt);
Date d1 = parseJwt.getIssuedAt();
Date d2 = parseJwt.getExpiration();
System.out.println("令牌签发时间:" + sdf.format(d1));
System.out.println("令牌过期时间:" + sdf.format(d2));
}
@Test
public void test5() {// 三秒后再解析上面过期时间只有三秒的令牌,因为过期则会报错io.jsonwebtoken.ExpiredJwtException
String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjI4NTMzMzAsImlhdCI6MTU2Mjg1MzMyNywidXNlcm5hbWUiOiJ6c3MifQ.e098Vj9KBlZfC12QSDhI5lUGRLbNwb27lrYYSL6JwrQ";
Claims parseJwt = JwtUtils.parseJwt(oldJwt);
// 过期后解析就报错了,下面代码根本不会执行
Date d1 = parseJwt.getIssuedAt();
Date d2 = parseJwt.getExpiration();
System.out.println("令牌签发时间:" + sdf.format(d1));
System.out.println("令牌过期时间:" + sdf.format(d2));
}
}
三、jwt与vuex配合在SPA项目中的应用
jwt与vuex的整合中讲过
结束!!!
|