1、引入pom
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2、写一个JWTUtils
public class JWTUtils {
//秘钥
private static final String jwtToken = "19971112miniipo!@#$%^&*";
public static String createToken(Long userId){
Map<String,Object> claims = new HashMap<>();
claims.put("userId",userId);
JwtBuilder jwtBuilder = Jwts.builder()
.signWith(SignatureAlgorithm.HS256,jwtToken)
.setClaims(claims)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 60 * 1000));
String token = jwtBuilder.compact();
return token;
}
public static Map<String,Object> checkToken(String token){
try {
Jwt parse = Jwts.parser().setSigningKey(jwtToken).parse(token);
return (Map<String, Object>) parse.getBody();
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
3、登录的时候调用工具类生成token
@Autowired
private RedisTemplate<String,String> redisTemplate;
@Override
public ResponseResult login(LoginDto loginDto) {
if (StringUtils.isEmpty(loginDto.getAccount()) || StringUtils.isEmpty(loginDto.getPassword())){
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE.getCode(),"请输入账号或密码");
}
String account = loginDto.getAccount();
String password = loginDto.getPassword();
//密码盐加密
String pwd = DigestUtils.md2Hex(password + slat);
ResponseResult responseResult = userService.findUser(account, pwd);
User user = (User) responseResult.getData();
if (StringUtils.isEmpty(user)){
return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST.getCode(),"用户名或密码不存在");
}
//前面是最简单的登录逻辑,基本可以忽略
//登陆成功 使用jwt生成token 返回token和存储到redis中
//这里是使用JWTUtils的创建token
String token = JWTUtils.createToken(user.getId());
//存到redis nosql数据库 顺带保存用户信息 user变成json格式的存到redis中
redisTemplate.opsForValue().set("TOKEN_" + token, JSON.toJSONString(user),1, TimeUnit.DAYS);
//给他返回回去 等于你登录后你就拿到一个token
return ResponseResult.okResult(token);
}
番外内容、拿到token怎么使用? 以下是我的使用过程。我用来做登录验证。后台有一个拦截器,只开放login和register和swaager给请求头没有携带token的请求访问、其他的接口都需要请求头携带token。 简单来说就是除了login和register可以直接访问,其他的请求接口都必须在请求头带token,拿到token后去redis数据库查询。因为上面代码我在redis数据库中存有用户信息,便可以获取用户信息
@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
@Autowired
private ILoginService loginService;
/**
在执行controller方法(Handler)之前进行执行
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)){
return true;
}
String token = request.getHeader("Authorization");
log.info("=================request start===========================");
String requestURI = request.getRequestURI();
log.info("request uri:{}",requestURI);
log.info("request method:{}",request.getMethod());
log.info("token:{}",token);
log.info("=================request end===========================");
if (token == null){
//ResponseResult 就是一个同一返回值,如果没有检测到token就直接返回未登录
ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN.getCode(), "未登录");
response.setContentType("application/json;charset=utf-8");
response.getWriter().println(JSON.toJSONString(result));
return false;
}
//如果token不为空,登录验证
User user = loginService.checkToken(token);
if (StringUtils.isEmpty(user)){
//ResponseResult 就是一个同一返回值,如果没有检测到token就直接返回未登录
ResponseResult result = ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN.getCode(), "未登录");
response.setContentType("application/json;charset=utf-8");
response.getWriter().print(JSON.toJSONString(result));
return false;
}
//token存在的话获取放行后的信息 用threadlocal存起来用户信息
UserThreadLocal.put(user);
return true;
}
/**
表示拦截器全部执行完毕后
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//不删除会内存泄露
UserThreadLocal.remove();
}
}
threadlocal代码
public class UserThreadLocal {
private UserThreadLocal(){
}
private static final ThreadLocal<User> LOCAL = new ThreadLocal<>();
/**
* 放
* @param user
*/
public static void put(User user){
LOCAL.set(user);
}
/**
* 拿
* @return
*/
public static User get(){
return LOCAL.get();
}
/**
* 删除
*/
public static void remove(){
LOCAL.remove();
}
}
拦截器代码 只有swagger、login、register可以在请求头不携带token访问
@Configuration
public class WebMVCConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addCorsMappings(CorsRegistry registry) {
//跨域配置,不可设置为*,不安全, 前后端分离项目,可能域名不一致
//本地测试 端口不一致 也算跨域
registry.addMapping("/**").allowedOrigins("http://localhost:9002");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/swagger-resources")
.excludePathPatterns("/api/v1/login")
.excludePathPatterns("/api/v1/register");
}
}
还可以使用ThreadLocal获取用户信息、后台管理系统增删改查人id等