项目搭建工具及版本:
eclipse / jdk1.8 / springboot2.5.0
实现功能:
未集成shiro。自定义拦截器实现对项目所有请求url的拦截与过滤,结合自定义token机制,用redis控制token的失效时间。同时配置文件里面增加token启停的开关,可以用来控制是否启停token的功能。
token的传输规则为:前端请求头中增加x_access_token的key设值然后传送到后端,后端对每个请求都进行拦截校验这个token,具体的规则可以自定义。
1.application-dev.properties配置文件用到的常量
#项目端口号和发布路径
server.port=8888
server.servlet.context-path=/bbnet
#是否启用token机制
token.check=false
#会话超时时间(秒)
token.session-out-time=1800
2.自定义全局拦截器、过滤器、常量类
package com.bbnet.config.interceptor;
import java.util.LinkedList;
import java.util.List;
/**
* 设置不需要拦截的请求
*
*
* @author sgc
* @since 2018年11月30日
*/
public class ExcludeParam {
/** 不拦截的请求列表 */
public final static List<String> reqPathList = new LinkedList<String>();
//不拦截的请求
static {
reqPathList.add("/error");
reqPathList.add("/swagger");
reqPathList.add("/webjars");
reqPathList.add("/csrf");
reqPathList.add("/druid");
reqPathList.add("/token");
}
}
package com.bbnet.config.interceptor;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
//import com.bbnet.common.exception.ErrorEnum;
//import com.bbnet.common.exception.ServiceException;
import com.bbnet.common.utils.StringUtil;
import com.bbnet.config.redis.RedisUtil;
import lombok.extern.slf4j.Slf4j;
/**
* 过滤器
*
* @author sgc
* @since 2018年11月30日
*/
@Slf4j
public class GlobalInterceptor implements HandlerInterceptor {
// /** 日志记录 */
// protected final Logger log = LoggerFactory.getLogger(GlobalInterceptor.class);
/** 不拦截的URL清单 */
private List<String> list = ExcludeParam.reqPathList;
@Autowired
private RedisUtil redisService;
@Value("${token.check}")
private boolean isCheckToken;
@Value("${token.session-out-time}")
private String sessionOutOfTime;
@Value("${server.servlet.context-path}")
private String contextPrefix;
/**
* 拦截所有请求,校验url和token
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String uri = request.getRequestURI();
//排除不需要拦截的请求URL
for (String u : list) {
if (uri.contains(u) || uri.equals("/") || uri.equals(contextPrefix+"/")) {
return true;
}
}
log.info("请求接口:" + uri);
//token校验
//token为{sysName}:user_prefix:{uId}用来校验用户是否登录或者登录超时
if(isCheckToken) {
return judgeURI(request, response);
}
return true;
}
/**
* 验证用户是否登录,如果未登录则转发到对应的登录界面,同时拦截ajax的请求
*
* @param request
* @param response
* @return
* @throws Exception
*/
private boolean judgeURI(HttpServletRequest request, HttpServletResponse response) throws Exception {
String token = request.getHeader("x_access_token");
log.info("请求token:" + token);
//是否正处于登录中
boolean isLogin = false;
if(StringUtil.isNull(token)) {
// log.error("token为空,请求已被拦截!");
//throw new ServiceException(ErrorEnum.RESP_CODE_NO_TOKEN);
} else {
boolean isExists = redisService.hasKey(token);
if(isExists) {
Object userSessionObj = redisService.get(token);
//登录中,重新更新redis中的超时时间
redisService.set(token, userSessionObj, Long.parseLong(sessionOutOfTime));
isLogin = true;
}else {
//未登录或已超时
//throw new ServiceException(ErrorEnum.RESP_CODE_TIMEOUT);
}
}
return isLogin;
}
/**
* 可以进行后续的日志记录,根据ex的值是否为null来判断是否需要做日子记录
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
package com.bbnet.config.interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import lombok.extern.slf4j.Slf4j;
/**
* 配置自定义拦截器
*
* @author avatar
* @since 2018年11月30日
*/
@Configuration
@Slf4j
public class InterceptorConfig implements WebMvcConfigurer {
// /** 日志记录 */
// protected final Logger log = LoggerFactory.getLogger(InterceptorConfig.class);
public void addInterceptors(InterceptorRegistry registry) {
// 拦截所有请求
registry.addInterceptor(globalInterceptor()).addPathPatterns("/**");
log.info("系统拦截器初始化完成");
}
@Bean
public GlobalInterceptor globalInterceptor() {
return new GlobalInterceptor();
}
}