SpringBoot拦截器的使用
作用:每次调接口先进拦截器(如果哪些请求地址不需要拦截可以配置里加入到白名单),主要用在平台登录。
具体使用:
- 创建我们自己的拦截器类并实现 HandlerInterceptor 接口
/**
1. 拦截器,每次调接口先进拦截器
2. 3. @author 苏育科
4. @date 2020/06/08 16:49
*/
@Slf4j
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Autowired
private RedisUtils redisUtils;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object object) {
//之里面主要写自己的拦截逻辑
//1.请求方式为OPTIONS直接跳过返回true
String method = httpServletRequest.getMethod();
if (method.equals(HttpMethod.OPTIONS.toString())) {
return true;
}
//2.获取IP,打印日志 TODO 后续优化为统一工具类
String ip = IpUtils.getIpAddress(httpServletRequest);
//3.从请求头获取Token
String token = httpServletRequest.getHeader("token");
//4.Token为空直接返回false
if (StringUtils.isBlank(token)) {
log.error("[拦截器] token为空,请求失败 ip=[{}]", ip);
addMessageToResponse(httpServletResponse, HttpStatus.UNAUTHORIZED);
return false;
}
//5.从Redis获取登陆用户信息
String userInfoKey = RedisKeyUtils.getUserInfoKey(token);
SystemUserVo systemUserVo = (SystemUserVo) redisUtils.get(userInfoKey);
//6.用户信息为空,代表登陆TOKEN已过期
if (null == systemUserVo) {
addMessageToResponse(httpServletResponse, HttpStatus.UNAUTHORIZED);
log.error("[拦截器] 用户信息过期,请重新登录 ip=[{}] token=[{}]", ip, token);
return false;
}
//7.重置Redis用户信息的过期时间
redisUtils.expire(userInfoKey, RedisConstants.SYSTEM_USERINFO.getExpireTime());
//8.设置Redis用户对应TOKEN的过期时间
String userTokenKey = RedisKeyUtils.getUserTokenKey(systemUserVo.getLoginName());
redisUtils.expire(userTokenKey, RedisConstants.SYSTEM_USERTOKEN.getExpireTime());
//8.把用户名和token存入Request,方便后面的使用
httpServletRequest.setAttribute("loginName", systemUserVo.getLoginName());
httpServletRequest.setAttribute("userName", systemUserVo.getName());
httpServletRequest.setAttribute("token", token);
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o, ModelAndView modelAndView) {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o, Exception e) {
}
/**
* 将异常信息写入响应体
*
* @param response HTTP响应
* @param httpStatus HTTP响应状态
* @throws IOException IO异常
*/
private void addMessageToResponse(HttpServletResponse response, HttpStatus httpStatus) {
//1.设置响应异常状态
response.setStatus(httpStatus.value());
response.setContentType("application/json;charset=UTF-8");
//2.响应异常信息写入
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
outputStream.write(httpStatus.getReasonPhrase().getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- 创建一个Java类继承WebMvcConfigurer,并重写 addInterceptors 方法。 实例化我们自定义的拦截器,然后将对像手动添加到拦截器链中(在addInterceptors方法中添加)。
/**
1. @author 苏育科
2. @date 2020/06/08 16:48
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private WhiteListConfig whiteListConfig;
@Bean
AuthInterceptor authlInterceptor() {
return new AuthInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
//获取白名单
List<String> whiteListUrl = whiteListConfig.getUrl();
registry.addInterceptor(authlInterceptor())
.addPathPatterns("/**")
//白名单里的url可以不通过拦截器
.excludePathPatterns(whiteListUrl);
}
}
- 白名单
/**
1. @author 苏育科
2. @date 2020-11-19 10:43:31
3. @describe:
*/
@Component
@ConfigurationProperties(prefix = "yuffie2.white-list")
@Data
public class WhiteListConfig {
/**
* 白名单的URL从配置文件里获取
*/
private List<String> url;
}
- 配置白名单
# 自定义配置
yuffie2:
# 白名单配置
white-list:
url:
- /swagger-resources/**
- /webjars/**
- /v2/**
- /swagger-ui.html/**
- /api/v1/tokens