需求分析
后台管理系统中除了登录接口、获取验证码的接口在访问的时候不需要验证用户的登录状态,其余的接口在访问的时候都必须要求用户登录成功以后才可以进行访问。
登录过程
前端请求url 经过拦截器(放行登录和验证码)进行判断获取到token,从Redis中查询数据是否存在,
若数据存在放在ThreadLocal线程变量中,更新redis token存储的时间并放行
若不存在返回208状态码 返回前端页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| package com.atguigu.spzx.common.util;
import com.atguigu.spzx.model.entity.system.SysUser;
public class AuthContextUtil {
private static final ThreadLocal<SysUser> threadLocal = new ThreadLocal<>() ;
public static void set(SysUser sysUser) { threadLocal.set(sysUser); }
public static SysUser get() { return threadLocal.get() ; }
public static void remove() { threadLocal.remove(); } }
|
拦截器Hander
UserAuthProperties 用于读取yml中的参数
1 2 3 4 5 6 7 8
| @Data @ConfigurationProperties(prefix = "spzx.auth") public class UserAuthProperties {
private List<String> noAuthUrls; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| @Component public class LoginAuthInterceptor implements HandlerInterceptor {
@Autowired RedisTemplate<String , String> redisTemplate;
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String method = request.getMethod(); if("OPTIONS".equals(method)){ return true; } String token = request.getHeader("token"); if(StrUtil.isEmpty(token)) { responseNoLoginInfo(response) ; return false ; }
String userInfoJSON = redisTemplate.opsForValue().get(CacheConstant.User_Login_Prefix + token); if(StrUtil.isEmpty(userInfoJSON)) { responseNoLoginInfo(response) ; return false ; } SysUser sysUser = JSON.parseObject(userInfoJSON, SysUser.class); AuthContextUtil.set(sysUser);
redisTemplate.expire(CacheConstant.User_Login_Prefix + token,30, TimeUnit.MINUTES);
return true; }
private void responseNoLoginInfo(HttpServletResponse response) { Result<Object> result = Result.build(null, ResultCodeEnum.LOGIN_AUTH); PrintWriter writer = null; response.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset=utf-8"); try { writer = response.getWriter(); writer.print(JSON.toJSONString(result)); } catch (IOException e) { e.printStackTrace(); } finally { if (writer != null) writer.close(); } }
@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { AuthContextUtil.remove(); } }
|
配置拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| @Component public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired LoginAuthInterceptor loginAuthInterceptor; @Autowired UserAuthProperties userAuthProperties;
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginAuthInterceptor) .excludePathPatterns(userAuthProperties.getNoAuthUrls()) .addPathPatterns("/**"); }
@Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowCredentials(true) .allowedOriginPatterns("*") .allowedMethods("*") .allowedHeaders("*") ; } }
|