首先引入pom依赖
com.auth0
java-jwt
3.10.3
添加拦截器配置类
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtInterceptor())
.addPathPatterns("/**") //拦截所有请求 通过判断token是否合法是否需要登录
.excludePathPatterns("/user/login","/user/register","/**/import","/**/export"); //需要排除的 URL 路径模式的参数,使用它可以指定哪些 URL 不应该被拦截器拦截。
}
@Bean
public JwtInterceptor jwtInterceptor () {
return new JwtInterceptor();
}
}
创建JwtUtil 工具类,生成Token 这里类的注解可以不用@Service 换成@Component 大致功能是相同的 都是将类注入IOC容器中进行管理
@Service
public class JwtUtil {
private static UserService staticuserService;
@Resource
private UserService userService;
//将动态的 userService 引入 静态方法 方便静态查询当前userToken方法
@PostConstruct
public void setUserService(){
staticuserService = userService;
}
/**
* 生成token
*/
public static String createToken(User user) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, 7); //默认令牌过期时间7天
JWTCreator.Builder builder = JWT.create();
return builder.withClaim("userid",String.valueOf(user.getUserid()))
//给builder 添加令牌
.withExpiresAt(calendar.getTime())
// 以password作为密钥 通过HMAC256算法进行加密
.sign(Algorithm.HMAC256(user.getPassword()));
}
public static User getCurrentUser(){
try {
// RequestContextHolder顾名思义,持有上下文的Request容器
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String token = request.getHeader("token");
if (StrUtil.isNotBlank(token)){
String userid = JWT.decode(token).getClaim("userid").asString();
return staticuserService.getById(Integer.parseInt(userid));
}
}catch (Exception e) {
// 获取数据异常
throw new ServiceException(DATA_ERROR);
}
return null;
}
}
axios请求接口的js文件设置请求头中的token (不必写在实例里面)
// request 拦截器
// 可以自请求发送前对请求做一些处理
// 比如统一加token,对请求参数统一加密
request.interceptors.request.use(config => {
config.headers['Content-Type'] = 'application/json;charset=utf-8';
let user = localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")):{}
if (user){
config.headers['token'] = user.token; // 设置请求头
}
return config
}, error => {
return Promise.reject(error)
});
然后检验发送的请求中 Header是否具有token
通过拦截器的preHandle方法拦截登录的请求头 获取token。此处的ServiceException见我主页的我的自定义异常类
public class JwtInterceptor implements HandlerInterceptor {
@Autowired
private UserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("Token");
if (!(handler instanceof HandlerMethod)){
return true;
}
// 获取失败 token不存在
if (StrUtil.isBlank(token)){
throw new ServiceException(TOKEN_NOT_EXIST);
}
/**
* 本处有逻辑错误:通过token寻找userid 若token修改则无法找到User(实际User存在) 控制台报错 220 用户不存在
*/
String userid;
try {
// 在TokenUtils中 用withClaim将token存放至本地存储
userid = JWT.decode(token).getClaim("userid").asString();
}catch (JWTDecodeException j){
throw new ServiceException(TOKEN_ERROR);
}
// 根据token查询数据库进行对比
User user = userService.getById(Integer.parseInt(userid));
if (user == null) {
throw new ServiceException(ACCOUNT_NOT_EXIST);
}
// 验证用户密码加签验证token
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
try{
jwtVerifier.verify(token);
}catch (JWTVerificationException e){
throw new ServiceException(ACCOUNT_NOT_EXIST);
}
return true;
}
}
在login登录实现类下 将token存储在userDto里,通过UserDto类与页面进行数据传输回显
@Override
public UserDto login(UserDto userDto) {
// 通过dto获取的数据查询对应的User
User one = getUserInfo(userDto);
if (one != null){
// 然后将User的数据传到userDto
BeanUtils.copyProperties(one,userDto);
String token = JwtUtil.createToken(one);
userDto.setToken(token);
return userDto;
}else {
throw new ServiceException(LOGIN_MOBLE_ERROR);
}
}
此时在控制台则能发现token生成成功。
最后在自己的请求登录的接口下面
将自己的user信息存放在本地存储空间
通过前端的接口拦截器,判断截取的状态码进行提示错误信息
// response 拦截器
// 可以在接口响应后统一处理结果
request.interceptors.response.use(
response => {
let res = response.data;
// 如果是返回的文件
if (response.config.responseType === 'blob') {
return res
}
// 兼容服务端返回的字符串数据
if (typeof res === 'string') {
res = res ? JSON.parse(res) : res
}
// 当验证不通过
if (res.code == '220') {
ElementUI.Message({
message : res.message,
type : 'error'
})
}
return res;
},
就实现JWT啦!