1.出现问题场景:
1.1 H5端的同事请求我一个获取验证码的接口,前提是H5端的同事在http的请求头中需要携带一个Token。后端是是SpringCloud写得,BaseController里面同意进行了跨域处理:
@CrossOrigin //统一处理跨域请求问题
@RestController
public class BaseController {
// 业务代码
}
1.2 服务端有一个Filter专门来验证H5端的Token有效新。当Token不合法和Token为空时分别分会不行的信息。(Token信息是通过JWT生成的)
@WebFilter(filterName = "jwtFilter", urlPatterns = "/api/*")
public class JwtFilter implements Filter {
private static Set<String> exceptURLs = new HashSet<>();
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String path = httpRequest.getServletPath();
if (exceptURLs.contains(path)) {
chain.doFilter(request, response);
return;
}
//处理复杂请求的预请求
if (httpRequest.getMethod().equals("OPTIONS")) {
httpResponse.setStatus(HttpServletResponse.SC_ACCEPTED);
chain.doFilter(request, response);
} else {
//验证Token,如果Token信息不合法或者为空的话就用httpRequest往前端发送提示信息
Claims claims = JwtUtil.verifyToken(httpRequest, httpResponse);
if (claims==null)
return;
chain.doFilter(request, response);
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
//初始化
}
}
2.问题分析:
2.1 按照上面1.1和1.2的方式的话,当前端的Token有误或者为空的话请求根本到不了Controller层的。所以BaseController的通用的跨域处理起不到作用。所以如果的JwtFilter的Response中也要做允许跨域处理。
3.解决方案:
3.1在检查前端的Token有误时,给Response设置对应允许跨域的响应头,如下:
//给前端响应信息,并且允许跨域请求
public static void sendJson(HttpServletResponse response, String data) throws IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
//允许跨域的请求的地址
response.setHeader("Access-Control-Allow-Origin", "*");
//允许请求头这种自定义字段
response.setHeader("Access-Control-Allow-Headers", "TOKEN");
//允许跨域请求的方法
response.addHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
//写响应信息
PrintWriter writer = response.getWriter();
writer.write(data);
writer.flush();
writer.close();
}