1.什么是jwt
JWT是JSON Web Token的简写,以Json形式做为web应用中的令牌,用于在各方之间安全地将信息作为json对象传输,传输过程中可以完成数据加密、签名等相关处理。
2.jwt能做什么
1.授权。
2.信息交换。
3.jwt有何优势
传统的session认证方式将session保存在服务端(一般是内存),通过客户端cookie的sessionid来找到对应的session实现认证。此方式有如下缺点:
1.随着认证用户的增加,服务器内存会随着增加。
2.如果session保存在服务器内存中,下次登录必须再次请求存session的服务器才能进行认证,限制了应用的扩展能力。
3.cookie有被截获的风险。
4.sessionid表达的信息不丰富,不容易扩展。
jwt认证是将用户信息作为JWT Payload(负载),将其与头部(header)分别进行Base64编码拼接后签名,形成一个jwt,格式为header.payload. signature(签名)。
相对传统的session认证,有如下优势:
1.简洁:可通过post参数或者在header中发送,数据小传输快。
2.自包含:负载中包含了所有用户需要的信息,避免多次查询。
3.跨语言:因为是json加密的形式,基本适用任何web应用。
4.无须在服务端保存,更适合分布式系统。
4.jwt的结构
1.标头(header)
标头由两部分组成,令牌类型(默认jwt)和签名算法 ,使用base64(可逆编码,非加密)编成jwt的第一部分。
2.负载(payload)
包含了声明,声明是用户相关实体和其它数据的声明。同样使用Base64编码。
3.签名(signature)
签名是jwt的重点,由编码后的标头和负载加上密钥再使用签名算法(标头中指定的算法)签名后得出。
如果标头中的签名算法为a,编码后的标头为x,编码后的负载为y,密钥为z,签名就是a(x+"."+y,z)。而整个jwt就是x.y.a(x+"."+y,z)。
值得注意的是因为负载的编码可逆,负载里不能存放敏感信息。
5.JWT的使用






6.封装工具类
public class JWTUtils {
//密钥
private static final String SING="!@#$%";
/**
* 生成token
*/
public static String getToken(Map<String,String> map){
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE,7); //7天过期
//创建Builder
JWTCreator.Builder builder = JWT.create();
//payload
map.forEach((k,v)->{
builder.withClaim(k,v);
});
String toekn = builder.withExpiresAt(instance.getTime())//过期时间
.sign(Algorithm.HMAC256(SING));//签名
return toekn;
}
/**
* 验证TOKEN
*/
public static void verify(String token){
JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
}
/**
* 获取token信息
*/
public static DecodedJWT getTokenInfo(String token){
DecodedJWT verify = JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
return verify;
}
}
7.整合springboot











以上实现了token的验证,但是每次都要传递token,可以用拦截器进行优化。
创建拦截类:
/**
* JWT拦截器
*/
public class JWTInterceptor implements HandlerInterceptor {
//处理请求前调用
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws IOException {
Map<String, Object> map = new HashMap<>();
//获取请求头中的token
String token = request.getHeader("token");
try {
JWTUtils.verify(token);
return true; //放行
} catch (SignatureVerificationException e) { //签名异常
e.printStackTrace();
map.put("msg","无效签名");
}catch (TokenExpiredException e) { //有效期异常
e.printStackTrace();
map.put("msg","token过期");
}catch (AlgorithmMismatchException e) { //算法异常
e.printStackTrace();
map.put("msg","算法不一致");
}catch (Exception e) {
e.printStackTrace();
map.put("msg","token无效");
}
map.put("state",false); //异常设置状态
String json = new ObjectMapper().writeValueAsString(map); //将对象转换为Json字符串
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
return false;
}
}
创建配置类:
/**
* 拦截器配置类
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new JWTInterceptor()) //拦截器
.addPathPatterns("/user/test") //拦截器的路径
.excludePathPatterns("/user/login"); //不需要拦截的路径
}
}

