springboot集成jwt进行token验证
- 导入jwt依赖包
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
2.封装token验证工具类
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.example.shopsystemspringboot.common.Constants;
import com.example.shopsystemspringboot.common.Result;
import com.example.shopsystemspringboot.entity.User;
import com.example.shopsystemspringboot.exception.ServiceException;
import com.example.shopsystemspringboot.service.UserService;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import com.auth0.jwt.JWTVerifier;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* token验证
*/
public class JwtInterceptor implements HandlerInterceptor {
@Resource
public UserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
// 如果不是映射到方法直接通过
if(!(handler instanceof HandlerMethod)){
return true;
}
// 执行认证
if (StringUtils.isEmpty(token)){
throw new ServiceException(Constants.CODE_401, "请重新登录");
}
// 获取 token 中的 user id
String userId = "";
try {
userId = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
throw new ServiceException(Constants.CODE_401, "验证失败,请重新登录");
}
// 根据token中的userid查询数据库
Result result = userService.getUserById(Long.valueOf(userId));
if (result.getData() == null) {
throw new ServiceException(Constants.CODE_401, "用户不存在,请重新登录");
}
// 用户密码加签验证 token
User user = (User) result.getData();
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
try {
jwtVerifier.verify(token); // 验证token
} catch (JWTVerificationException e) {
throw new ServiceException(Constants.CODE_401, "验证失败,请重新登录");
}
return true;
}
}
3.扩展WebMvcConfigurationSupport类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtInterceptor())
.addPathPatterns("/**") // 拦截所有请求,通过判断token是否合法来决定是否需要登录
.excludePathPatterns("/user/login"); // 无须验证可以请求
}
@Bean
public JwtInterceptor jwtInterceptor() {
return new JwtInterceptor();
}
}
4.当用户登录时,返回token给前端保存
@Override
public Json login(UserCondition user) {
Json json = new Json();
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getUsername,user.getUsername());
queryWrapper.eq(User::getPassword,user.getPassword());
queryWrapper.eq(User::getDeleteStatus,0);
try {
User one = this.getOne(queryWrapper);
if (one != null){
// 设置token
String token = TokenUtils.genToken(one.getId(), user.getPassword());
one.setToken(token);
// 返回数据
json.setSuccess(true);
json.setMsg("登录成功");
json.setObj(one);
return json;
}else {
json.setSuccess(false);
json.setMsg("用户名或者密码错误");
return json;
}
}catch (Exception e){
e.printStackTrace();
json.setSuccess(false);
json.setMsg(e.getMessage());
return json;
}
}
- User实体类定义token属性
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import nonapi.io.github.classgraph.json.Id;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@TableName(value = "sys_user")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
@Excel(exportName = "用户名")
private String username;
@JsonIgnore // 该字段不会显示在前端
private String password;
@Excel(exportName = "昵称")
private String nickname;
@Excel(exportName = "邮箱")
private String email;
@Excel(exportName = "电话")
private String phone;
@Excel(exportName = "地址")
private String address;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
// 删除状态-- 0:未删除 1:已删除
@TableField(fill = FieldFill.INSERT)
private Integer deleteStatus;
@TableField(exist = false)
private String token;
}
6.登录成功后前端保存user参数
login() {
this.$refs['userForm'].validate((valid) => {
if (valid) { // 表单校验合法
this.request.post("/user/login", this.user).then(res => {
console.log(res)
if (res.success) {
localStorage.setItem("user", JSON.stringify(res.obj)) // 存储用户信息到浏览器
this.$message.success("登录成功")
this.$router.push("/")
} else {
this.$message.error(res.msg)
}
})
}
});
}
7.vue前端发送请求时携带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")) : null
if (user) {
config.headers['token'] = user.token; // 设置请求头
}
return config
}, error => {
return Promise.reject(error)
});