基于session和基于jwt的方式的主要区别就是用户的状态保存的位置,session是保存在服务端的,而jwt是保存在客户端的,为分布式系统提供了便利。
JWT全称为JSON Web Token,是一种用于身份验证的标准。而Token一般指的是验证/身份标识。因此,可以将JWT看作是Token的一种特定实现。JWT主要是用来做认证的,它由三段信息组成,分别是头部、载荷和签证,三段信息用"."连接起来构成jwt字符串。
在使用过程中首先导入jwt依赖,然后写jwt生成工具类(这里可以设置用户id作为载荷,token的过期时间,以密码作为生成token的签证等来创造jwt),前端登录的时候查询用户是否存在,如果存在生成jwt响应给前端;此后前端每次请求系统接口的都会携带jwt,通过拦截器拦截请求验证jwt,只有携带jwt且正确有效才能访问数据,否则返回错误信息。
1.导入依赖
com.auth0
java-jwt
3.7.0
2.写JwtUtil生成工具类
@Component
public class TokenUtils {
//生成token
public static String genToken(String userId, String sign) {
return JWT.create().withAudience(userId) // 将 user id 保存到 token 里面,作为载荷
.withExpiresAt(DateUtil.offsetHour(new Date(), 2)) // 2小时后token过期
.sign(Algorithm.HMAC256(sign)); // 以 password 作为 token 的密钥
}
}
3.新建实体类
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
private Integer id;
private String username;
private String password;
private String token;
}
4.新建UserMapper接口
@Mapper
public interface UserMapper{
/*登录方法*/
User login(User user);
}
5.新建UserMapper.Xml
6.UserService接口
public interface IUserService extends IService {
User login(User user);
}
7.UserServiceImpl
@Service
public class UserServiceImpl extends ServiceImpl implements IUserService {
@Resource
UserMapper userMapper;
@Override
public User login(User user) {
User user1 = userMapper.login(user);
if (user1 != null) {
String token = TokenUtils.genToken(user1.getId().toString(), user1.getPassword());
user.setToken(token);
return user;
} else {
throw new ServiceException(Constant1.CODE_600, "用户名或密码错误");
}
}
}
8.UserController
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
IUserService userService;
@Autowired
UserServiceImpl userServiceimp;
@PostMapping("/login")
public Result login(@RequestBody User user) {
User user = userService.login(user);
return Result.success(user);
}
9.前端请求头中设置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; // 设置请求头
}
10.给请求添加拦截器用于验证token
//token拦截器
public class JwtInterceptor implements HandlerInterceptor {
@Autowired
private IUserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("token");//从http请求头中获取token
// 如果不是映射到方法直接通过
if(!(handler instanceof HandlerMethod)){
return true;
}
// 执行认证
if (StrUtil.isBlank(token)) {
throw new ServiceException(Constants.CODE_401, "无token,请重新登录");
}
// 获取 token 中的 user id
String userId;
try {
userId = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
throw new ServiceException(Constants.CODE_401, "token验证失败,请重新登录");
}
// 根据token中的userid查询数据库
User user = userService.getById(userId);
if (user == null) {
throw new ServiceException(Constants.CODE_401, "用户不存在,请重新登录");
}
// 用户密码加签验证 token
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
try {
jwtVerifier.verify(token); // 验证token
} catch (JWTVerificationException e) {
throw new ServiceException(Constants.CODE_401, "token验证失败,请重新登录");
}
return true;
}
}
11.注册拦截器
//注册拦截器
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtInterceptor())
.addPathPatterns("/**") // 拦截所有请求,通过判断token是否合法来决定是否需要登录
.excludePathPatterns("/user/login", "/user/register", "/**/export","/file/**", "/**/import");
// "/file/**",
// "/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**", "/api", "/api-docs", "/api-docs/**")
// .excludePathPatterns( "/**/*.html", "/**/*.js", "/**/*.css", "/**/*.woff", "/**/*.ttf");
// 放行静态文件
}
//将对象注入到容器中
@Bean
public JwtInterceptor jwtInterceptor() {
return new JwtInterceptor();
}
推荐
什么是JWT?(细致讲解)_Ethereal@_@的博客-CSDN博客https://blog.csdn.net/weixin_45410366/article/details/125031959