JWT是什么?
JSON Web Token (JWT),它是目前最流行的跨域身份验证解决方案,该token被设计为紧凑而安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其他业务逻辑所必须的声明信息,该token也可直接被用于认证,也可以被加密
为什么使用JWT?
JWT的精髓在于:“去中心化”,数据是保存在客户端的
JWT的工作原理:
-
是在服务器身份验证之后,将生成一个JSON对象并将其发送回用户,示例如下:
{“UserName”: “Chongchong”,“Role”: “Admin”,“Expire”: “2018-08-08 20:15:56”} -
之后,当用户与服务器通信时,客户在请求中发回JSON对象
-
为了防止用户篡改数据,服务器将在生成对象时添加签名,并对发回的数据进行验证
JWT组成
一个JWT实际上就是一个字符串,它由三部分组成:
- 第一部分:header 头部(声明类型,声明加密的算法)
- 第二部分:payload 载荷(载荷就是存放有效信息的地方)
- 第三部分:signature 签证(jwt的第三部分是一个签证信息)
案例
在登录时保存jwt令牌在request Header,WEB APP项目每次请求后台数据时(将JWT令牌从请求头中带过来),验证通过,刷新JWT,并保存在响应头返回给客户端
后端
JwtFilter
package com.tang.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;
/**
* * 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 = false;// true关闭jwt令牌验证功能
@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 v