springboot项目+redis验证token
pom文件中导入对应jar包
<!--jwt生成token验证token-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--pageHelper坐标-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.7</version>
</dependency>
<!--redis坐标-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
jwt工具类 生成token并验证token有效性
package com.itheima.bigevent.utills; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; import java.util.Date; import java.util.Map; /** * @author*/ public class JwtUtil { private static final String KEY="itheima"; /** *接收业务数据生成token * @param claims * @return */ public static String genToken(Map<String,Object> claims){ //生成jwt String token = JWT.create() //添加载荷 .withClaim("claims",claims) //过期时间 .withExpiresAt(new Date(System.currentTimeMillis()+1000*60*60*12)) //指定算法配置秘钥 .sign(Algorithm.HMAC256(KEY)); System.out.println("token===:"+token); return token; } /** * 接收token验证token并返回数据 * @param token * @return */ public static Map<String,Object> parseToken(String token){ JWTVerifier verifier = JWT.require(Algorithm.HMAC256(KEY)).build(); //验证token,生成一个解析后的jwt对象 DecodedJWT decodedJWT = verifier.verify(token); Map<String, Object> claims = decodedJWT.getClaim("claims").asMap(); return claims; } }
ThreadLocalUtil工具类 把解析的用户信息放入ThreadLocal中
package com.itheima.bigevent.utills; /** * @author*/ public class ThreadLocalUtil { /** * 提供threadLocal对象 */ private static final ThreadLocal THREAD_LOCAL = new ThreadLocal<>(); /** * 根据key获取值 * @return * @param <T> */ public static <T> T get(){ return (T) THREAD_LOCAL.get(); } /** * 存储键值对 * @param value */ public static void set(Object value){ THREAD_LOCAL.set(value); } /** * 清除threadLocal防止内存泄漏 */ public static void remove(){ THREAD_LOCAL.remove(); } }
//自定义拦截器验证token
package com.itheima.bigevent.interceptors; import com.itheima.bigevent.utills.JwtUtil; import com.itheima.bigevent.utills.ThreadLocalUtil; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import java.util.Map; /** * @author*/ @Component public class LoginInterceptor implements HandlerInterceptor { @Autowired private StringRedisTemplate redisTemplate; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String url = request.getRequestURI(); System.out.println("请求路径url==="+url); //令牌验证 String token = request.getHeader("Authorization"); try{ //解析token Map<String,Object> map = JwtUtil.parseToken(token); Integer userId = (Integer) map.get("id"); System.out.println("解析token-map=="+map); //从redis中获取相同的token String key = "accessToken:token:"+userId; String redisToken = redisTemplate.opsForValue().get(key); if(null == redisToken){ throw new RuntimeException("token失效"); } //把业务数据存放到ThreadLocal中 ThreadLocalUtil.set(map); //放行 return Boolean.TRUE; }catch (Exception e){ e.printStackTrace(); response.setStatus(401); //不放行 return Boolean.FALSE; } } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { //清空treadLocal中数据 ThreadLocalUtil.remove(); } }
WebConfig配置文件,把自定义拦截器添加到配置中
package com.itheima.bigevent.config; import com.itheima.bigevent.interceptors.LoginInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @author*/ @Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private LoginInterceptor loginInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { //登陆接口和注册接口不拦截 registry.addInterceptor(loginInterceptor) // 只拦截/api开头的路径 .addPathPatterns("/api/**") //放行路径 .excludePathPatterns("/api/user/login","/user/register","/api/article/getAll"); } @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") //允许哪些域访问 .allowedOriginPatterns("*") //方法 .allowedMethods("GET", "POST", "PUT", "DELETE","HEAD", "OPTIONS") .allowedHeaders("*") //3600秒之内浏览器不必再次询问 .maxAge(3600) //允许携带cok .allowCredentials(true); } }
对应用户controller提供用户注册登陆方法
package com.itheima.bigevent.controller; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.itheima.bigevent.pojo.Result; import com.itheima.bigevent.pojo.User; import com.itheima.bigevent.pojo.UserReq; import com.itheima.bigevent.service.UserService; import com.itheima.bigevent.utills.JwtUtil; import com.itheima.bigevent.utills.ThreadLocalUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.util.DigestUtils; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; /** * @author * */ @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @Autowired private StringRedisTemplate redisTemplate; @PostMapping("/register") public Result register(String username,String password){ System.out.println("注册开始>>>>>>>>>>>>>"); if(StrUtil.isEmpty(username)){ return Result.error("用户名不能为空"); } if(StrUtil.isEmpty(password)){ return Result.error("密码不能为空"); } //查询用户 User user = userService.findByUserName(username); System.out.println("user===:"+user); if(null == user){ //注册 userService.register(username,password); return Result.success(); }else { //占用 return Result.error("用户名被占用"); } } @PostMapping("/login") public Result<String> login(String username,String password){ if(StrUtil.isEmpty(username)){ return Result.error("用户名不能为空"); } if(StrUtil.isEmpty(password)){ return Result.error("密码不能为空"); } //查询用户 User user = userService.findByUserName(username); if(ObjectUtil.isEmpty(user)){ return Result.error("用户不存在"); } if(!DigestUtils.md5DigestAsHex(password.getBytes()).equals(user.getPassword())){ return Result.error("密码错误!"); } //生成token Map<String,Object> claims = new HashMap<>(); claims.put("id",user.getId()); claims.put("username",user.getUsername()); claims.put("nickname",user.getNickname()); String token = JwtUtil.genToken(claims); //把token存储到redis中 String key = "accessToken:token:"+user.getId(); redisTemplate.opsForValue().set(key,token,30, TimeUnit.MINUTES); return Result.successDate(token); } /** * 获取用户信息 * @return */ @GetMapping("/getUserInfo") public Result<User> getUserInfo(@RequestHeader("Authorization") String token){ /* Map<String,Object> map = JwtUtil.parseToken(token); System.out.println("获取用户信息map=="+map); String username = map.get("username").toString();*/ Map<String,Object> map = ThreadLocalUtil.get(); System.out.println("map==="+map); String username = map.get("username").toString(); User user = userService.findByUserName(username); return Result.successDate(user); } @PostMapping("/update") public Result<Boolean> update(@Validated @RequestBody User user){ userService.update(user); return Result.successDate(Boolean.TRUE); } /** * 更新用户头像 * @param user * @return */ @PostMapping("updateUserPic") private Result<Boolean>updateUserPic(@RequestBody User user){ userService.updateUserPic(user); return Result.successDate(Boolean.TRUE); } /** * 更新用户密码 * @param user * @return */ @PostMapping("updatePassword") private Result<Boolean>updatePassword(@RequestBody UserReq user){ userService.updatePassword(user); Map<String,Object> map =ThreadLocalUtil.get(); Integer userId = (Integer) map.get("id"); //删除token String key = "accessToken:token:"+userId; redisTemplate.delete(key); return Result.successDate(Boolean.TRUE); } }
yaml配置文件
# server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/mybatis username:自己数据库用户名 password: 自己数据库密码 # redis配置 data: redis: host: localhost port: 6379 database: 0 mybatis: configuration: #开启驼峰命名和下划线命名字段的自动转换 map-underscore-to-camel-case: true mapper-locations: classpath*:mapper/**/*.xml

浙公网安备 33010602011771号