拦截器
import com.alibaba.fastjson.JSONObject;
import com.citrsw.shangshangpin.common.Constant;
import com.citrsw.shangshangpin.common.JwtUtil;
import com.citrsw.shangshangpin.common.Msg;
import com.citrsw.shangshangpin.common.Result;
import com.citrsw.shangshangpin.entity.Personnel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* 登录拦截器
*
* @author Zhenfeng Li
* @version 1.0.0
* @date 2020-02-19 16:47:31
*/
@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
@Value("${spring.mvc.servlet.path:}")
private String servletPath;
private final RedisTemplate<String, Object> redisTemplate;
public LoginInterceptor(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
String token = request.getHeader("authorization");
if (StringUtils.isBlank(token)) {
//重置response
response.reset();
//设置编码格式
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(JSONObject.toJSONString(Result.build(Msg.TOKEN_FAIL, Msg.TEXT_TOKEN_INVALID_FAIL)));
log.debug("员工token失效");
return false;
}
Personnel personnel = JwtUtil.verifyPersonnelToken(token);
if (personnel == null) {
//重置response
response.reset();
//设置编码格式
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(JSONObject.toJSONString(Result.build(Msg.TOKEN_FAIL, Msg.TEXT_TOKEN_INVALID_FAIL)));
log.debug("员工token失效");
return false;
}
//从token中解析出员工Id,与redis中的token比对,存入session以备后用
String redisToken = (String) redisTemplate.opsForValue().get(Constant.ON_LINE_PERSONNEL_PREFIX + personnel.getId());
if (redisToken == null) {
//重置response
response.reset();
//设置编码格式
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(JSONObject.toJSONString(Result.build(Msg.TOKEN_FAIL, Msg.TEXT_TOKEN_INVALID_FAIL)));
log.debug("员工token失效");
return false;
}
//判断token是否一致
if (!token.equals(redisToken)) {
//重置response
response.reset();
//设置编码格式
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(JSONObject.toJSONString(Result.build(Msg.TOKEN_FAIL, Msg.TEXT_TOKEN_INVALID_FAIL)));
log.debug("员工token失效");
return false;
}
request.getSession().setAttribute(Constant.PERSONNEL_KEY, personnel);
//操作后,延长redis中无操作自动离线倒计时时间
redisTemplate.expire(Constant.ON_LINE_PERSONNEL_PREFIX + personnel.getId(), Constant.ON_LINE_TIME_PERSONNEL, TimeUnit.SECONDS);
log.info("操作人Id[{}],请求方式[{}],请求路径[{}]", personnel.getId(), request.getMethod(), request.getRequestURI().replaceFirst(servletPath, ""));
return true;
}
}
拦截器配置
/**
* 拦截器配置
*
* @author Zhenfeng Li
* @date 2020-01-07 15:15:11
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
private final LoginInterceptor loginInterceptor;
public InterceptorConfig(LoginInterceptor loginInterceptor) {
this.loginInterceptor = loginInterceptor;
}
/**
* 注册参数解析器
*
* @param argumentResolvers
*/
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new CustomServletModelAttributeMethodProcessor(true));
}
/**
* 放行API
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/citrsw/**").addResourceLocations("classpath:/citrsw/");
}
/**
* 配置拦截器执行顺序
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 多个拦截器组成一个拦截器链
// 默认全部拦截
// addPathPatterns 添加拦截
// excludePathPatterns 排除拦截
//order值越小越靠前,此处配置有效
//登录拦截器
registry.addInterceptor(loginInterceptor)
//需要拦截的uri
.addPathPatterns("/**")
//需要跳过的uri
.excludePathPatterns("/app/**", "/public/**", "/register", "/login", "/logout", "/verification/msg", "/forget", "/verification/img", "/verification/img/check", "/citrsw/**")
//拦截器的执行顺序 设置高一点方便后期扩展
.order(1);
}
}