使用JWT验证登陆(拦截器实现)
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
JSON Web Token由三部分组成,它们之间用圆点(.)连接。这三部分分别是:
- Header
- Payload
- Signature
因此,一个典型的JWT看起来是这个样子的:
xxxxx.yyyyy.zzzzz
详细了解可查看: 知乎:5分钟带你了解JWT
1.引入jwt的jar包。
<!--引入JWT-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.0</version>
</dependency>
2.编写token工具类,其中包含生成token方法 和 验证token方法。
package cn.pjh.everyDay.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Calendar;
import java.util.Map;
public class JWTUtils {
//加密盐 使用它来加密解密
private static final String sign = "9jIWOD9idje91@#*9wofj+%5895d123";
/**
* 生成token header.payload.sign
*/
public static String getToken(Map<String,String> map){
//生成过期时间
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND,20);
JWTCreator.Builder builder = JWT.create();
//将传入进来的参数存入token,比如用户id
map.forEach((k,v)->{
builder.withClaim(k,v);
});
//生成token使用HMAC256算法
String token = builder.withExpiresAt(instance.getTime())
.sign(Algorithm.HMAC256(sign));
return token;
}
/**
* 获取token信息方法
*/
public static DecodedJWT getTokenInfo(String token){
//解析token拿出内容,加密的时候使用的什么算法这里就要用什么算法解析(HMAC256)
DecodedJWT verify = JWT.require(Algorithm.HMAC256(sign)).build().verify(token);
return verify;
}
}
3.编写拦截器类
package cn.pjh.everyDay.interceptors;
import cn.pjh.everyDay.common.R;
import cn.pjh.everyDay.utils.JWTUtils;
import com.alibaba.fastjson.JSON;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class JWTInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//从请求头中获取token
String token = request.getHeader("token");
//如果验证未成功直接拦截,并返回原因
R r = new R<>();
try {
//验证token
JWTUtils.getTokenInfo(token);
//验证成功没有异常直接放行
return true;
}catch (SignatureVerificationException e){
e.printStackTrace();
//签名不对抛出的异常
r.setCode(0);
r.setMsg("无效签名");
}catch (TokenExpiredException e){
//token过期抛出的异常
e.printStackTrace();
r.setCode(0);
r.setMsg("登陆验证过期");
}catch (AlgorithmMismatchException e){
//算法不一致发生的异常
e.printStackTrace();
r.setCode(0);
r.setMsg("登陆异常");
}
//转存json字符串通过response打印流返回给客户端
String r1 = JSON.toJSONString(r);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(r1);
return false;
}
}
4.将拦截器注册到mvc
package cn.pjh.everyDay.config;
import cn.pjh.everyDay.interceptors.JWTInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//mvc配置类中添加拦截器
registry.addInterceptor(new JWTInterceptor())//需要添加的拦截器类
.addPathPatterns("/**")//需要拦截的路径
.excludePathPatterns("user/login");//需要排除的路径
}
}
5.编写登陆接口()
@PostMapping("/login")
public R<Map> loginUser(User user) {
//数据库查找到当前用户
User u = userService.getById(user);
//如果查询到数据就登陆成功否则失败
if (u != null){
//将需要token存储的信息放入map集合
Map<String, String> map = new HashMap<>();
map.put("id", u.getId().toString());
//通过工具类生成token
String token = JWTUtils.getToken(map);
//返回一个当前用户的信息和token的map集合,然后交给前端人员,设置访问时将token设置到请求头里面
Map<String, Object> r = new HashMap<>();
r.put("userId", u.getId());
r.put("username", u.getName());
r.put("phone", u.getPhone());
r.put("token", token);
return R.success(r);
}
return R.error("请检查账号或密码");
}
登陆成功之后前端将返回数据里面的token保存在localStorage或者sessionStorage中,之后每次访问将token设置到请求头里面进行访问。
退出账号则前端直接删除掉本地的token。
还没有评论,来说两句吧...