拦截器
/**
* 在Zuul转发请求前拦截
*
* @author huangJunHao
* @date 2022/3/11
*/
@Component
public class PreFilter extends ZuulFilter {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private IRedisService redisService;
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest httpServletRequest = ctx.getRequest();
HttpServletResponse httpServletResponse = ctx.getResponse();
//获取路径,白名单不拦截
String writeURI = httpServletRequest.getRequestURI();
SoftReference<ArrayList<String>> listSoftReference = new SoftReference<>(new ArrayList<>());
ArrayList<String> writeUrls = listSoftReference.get();
//因为用的是软引用对象,所以可能被GC,要先判断是否为空
if (writeUrls == null) {
listSoftReference = new SoftReference<>(new ArrayList<>());
}
writeUrls = listSoftReference.get();
//白名单URL,不走过滤器
writeUrls.add("/user/getSign");
//writeUrls.add("/user/test");
writeUrls.add("/user/logout");
writeUrls.add("/user/login");
writeUrls.add("/user/testLogin");
writeUrls.add("/user/encryptAccount");
writeUrls.add("/user/getVerifyCode");
if (writeUrls.contains(writeURI)) {
return true;
}
//首先从请求头中获取token串,与页面约定好存放token值的请求头属性名为x-token
String token = httpServletRequest.getHeader("x-token");
logger.info("[登录校验拦截器]-token为:{}", token);
//判断token是否有效
if (StringUtils.isNotBlank(token)) {
//从Redis获取到用户信息,获取不到说明token失效了;否则直接返回token
try {
User user = redisService.getUser(httpServletRequest);
if (user != null) {
httpServletResponse.setHeader("x-token", token);
return true;
}
} catch (Exception e) {
e.printStackTrace();
logger.error("[PreFilter]-redisService,从Redis获取到用户信息错误");
}
} else {
logger.info("[PreFilter]-token非法或已超时,重新登录");
}
//输出响应流
ctx.setSendZuulResponse(false);
Map<String, Object> resp = new HashMap<>(4);
resp.put("code", ResultEnum.NOT_LOGIN.getCode());
resp.put("msg", "用户没有登录");
ctx.setResponseBody(JSONObject.toJSONString(resp));
ctx.getResponse().setContentType("application/json; charset=utf-8");
try {
// 调用flushBuffer刷新缓冲区数据即可
ctx.getResponse().flushBuffer();
} catch (IOException e) {
e.printStackTrace();
logger.error("[PreFilter]-flushBuffer,调用flushBuffer刷新缓冲区数据错误");
}
return null;
}
/**
* 获取Ip地址
*
* @param request
* @return
*/
public String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
pom
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
配置文件 所有:localhost:8080/user/*的接口都会到8091端口
zuul:
routes:
#user微服务
userService:
#以/user为头部的请求都转发到onstore-user服务里
path: /user/**
serviceId: onstore-user
#url: http://localhost:8091
ribbon:
#解决zuul转发请求导致的超时问题
ReadTimeout: 60000
SocketTimeout: 60000
启动类加上
@EnableZuulProxy
|