JWT工具
JWT(json web Token) 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准.
JWT的声明一般用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,比如用户登录上
JWT最重要的作用是对token信息的防伪作用
JWT原理
一个JWT由三个部分组成->公共部分(加密算法部分),私有部分,签名部分.最后由这三者组合进行base64编码得到JWT
引入依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
一个拦截类
package com.dlf.springlogin.interceptors;
import com.dlf.springlogin.annotations.LoginRequired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class LogInterceptor implements HandlerInterceptor {
/**
* 需要拦截的有三类
* 第一类:不需要进行拦截的方法(没有拦截器注解),直接放行
* 第二类:需要拦截器进行拦截,但是拦截校验失败(用户没有登录或者登录过期了)也可以继续访问的方法,比如说购物车中的方法
* 登录之后用的是一个分支,不登录又是另一个分支,(登录之后购物车信息存数据库,不登录依然可以添加购物车 这个时候购物信息存的是cookie)
* 第三类:需要拦截,并且拦截校验一定要通过(用户登录成功了)才能访问的方法
*/
//业务处理器处理请求之前被调用,对用户的request进行处理
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//拦截代码
// 判断被拦截的请求的访问方法的注解(是否需要拦截的)
//Java反射 通过类,对象,类名 来得到类的信息
HandlerMethod hm = (HandlerMethod) handler; //通过方法名得到方法的信息---->Java反射
LoginRequired loginRequired = hm.getMethodAnnotation(LoginRequired.class); //得到方法上面的注解
if (loginRequired == null) {
return true;
} else {
String token = ""; //这一步获取前端传过来的token
boolean loginSuccess = loginRequired.loginSuccess(); //获取注解的标记 表示获取该请求是否必须要登录成功
if (loginSuccess) {//loginSuccess = true 第三类 必须登录
if (StringUtils.isEmpty(token)) {
//如果token为空 返回
} else {
//token 不为空
String success = judgeToken(); //远程调用认证中心认证token是否通过
if (success.equals("success")) {//表示token合法
// 验证通过 -> 覆盖token 重置token的过期时间
return true;
}
}
} else { //第二类 登不登录都可以 只是登录和不登录的处理方式不一样
}
// 进入拦截器的拦截方法
}
return true;
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
一个登陆的测试方法 登陆成功之后就返回用户信息生成的token
@GetMapping("login")
public String handleLogin() {
User user =loginq.handleLogin();
Map<String,Object> map = new HashMap<>();
map.put("userName",user.getUserName());
map.put("password",user.getPassword());
String ip = "127.0.0.1";
String time = new SimpleDateFormat("yyyyMMdd HHmm").format(new Date());
String token = JwtUtil.encode("2017081180",map,ip+time);
//下一步再把token存到Redis里面就行了
return token;
}
另一个解析token的测试方法
@GetMapping("decode")
public Map<String, Object> decodeToken(String token) {
String decodes = "";
Map<String, Object> decode = JwtUtil.decode(token, "2017081180", "127.0.0.1");
return decode;
}
接下来就是token的加密和解密方法
public class JwtUtil {
/**
* 加密算法
* @param key 服务器公共信息 这个key是服务器才有的 只有服务器才知道,代表了服务器的身份
* @param param 用户的基本信息
* @param salt 盐值 浏览器上的 salt(ip,time)
* 这样的话token就绑定了 浏览器 服务器 用户信息 只要这三者有一个变了,就会导致整个token验证失败
* @return
*/
public static String encode(String key, Map<String,Object> param,String salt){
if(salt!=null){
key+=salt;
}
JwtBuilder jwtBuilder = Jwts.builder().signWith(SignatureAlgorithm.HS256,key);
jwtBuilder = jwtBuilder.setClaims(param);
String token = jwtBuilder.compact();
return token;
}
/**
* token 解密
* @param token
* @param key
* @param salt
* @return
*/
public static Map<String,Object> decode(String token,String key,String salt){
Claims claims = null;
if(salt!=null){
key+=salt;
}
try{
claims = Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody();
}catch (JwtException e){
return null;
}
return claims;
}
}
在加密的时候给token的map里面加了那些元素,解密的时候就能够通过map拿到这些元素.
下图就是根据token解析获得的值
当然token的加密算法有很多种 这里展示的只是最简单的一种