package com.tensquare.manager;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import util.JwtUtil;
import javax.servlet.http.HttpServletRequest;
@Component
public class ManagerFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Autowired
private JwtUtil jwtUtil;
@Override
public Object run() throws ZuulException {
System.out.println("管理后台网关zuul过滤器");
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
if(request.getMethod().equals("OPTIONS")){
return null;
}
String url = request.getRequestURL().toString();
if(url.indexOf("/admin/login")>0){
System.out.println("登陆页面");
return null;
}
String authHeader = request.getHeader("Authorization");
if(authHeader!=null && authHeader.startsWith("Bearer ") ){
String token = authHeader.substring(7);
Claims claims = jwtUtil.parseJWT(token);//解析token
if(claims!=null){
if("admin".equals(claims.get("roles"))){
requestContext.addZuulRequestHeader("Authorization",authHeader);
System.out.println("token 验证通过,添加了头信息:"+authHeader);//转发header,原始header转发会丢失
return null;//过滤器正常结束,转发路由
}
}
}
requestContext.setSendZuulResponse(false);// 终止运行,不影响过滤器后面代码执行
HttpServletResponse response = requestContext.getResponse();
AjaxResult ajaxResult = new AjaxResult(403,"请登录");
ObjectMapper objectMapper = new ObjectMapper();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=utf-8");
try {
String ajaxresultjson = objectMapper.writeValueAsString(ajaxResult);//必须转成json格式,不然跟contenttype格式不符合
response.getWriter().write(ajaxresultjson);
} catch (Exception e) {
e.printStackTrace();
}
}
}
目前项目结构是VUE做前端,后端采用微服务架构,在开发时前端需要跨域请求数据,通过CorsConfig配置解决了简单跨域请求需要。但当需要在请求的header中增加token信息时,出现了请求失败的情况,浏览器和后台均出现OPTIONS类型请求相关提示。
搜索资料后发现,在设置了header之后,浏览器在发送正式请求前,会先发送一个OPTIONS请求,(据资料)发送OPTIONS请求是为了验证正式请求的有效性,检查服务端是否支持正式请求类型(POST、GET 等),但不清楚服务端底层框架在默认情况下时怎么响应该请求的。而OPTIONS请求中不包含任何用户参数,导致ZUUL中的过滤类型为 pre 的过滤器中的用户校验失败,从而返回用户提示信息,就无法继续执行正式请求了。
有资料说需要服务端返回一个状态是200的响应,但测试直接返回status为200的响应并没有产生作用,浏览器端仍然会显示请求失败,并不会执行正式请求