H5请求服务端发送POST请求之预请求-OPTIONS

1.问题场景

1.1 H5端请求服务端接口时,需要在header中携带服务端用jwt规范生成的token

1.2 在接收到H5的请求时Filter需要从请求头中拿出token做校验,检查当前的token是否是合法的。然后根据校验结果做出对应的响应,token合法就放行,不合法就返回错误信息。

@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();
        //判断当前请求的接口是否需要检查token的合法性
        if (exceptURLs.contains(path)) {
            chain.doFilter(request, response);
            return;
        }
          //我们需要验证token的url中就检查token的合法性
            Claims claims = JwtUtil.verifyToken(httpRequest, httpResponse);
            MDC.put("remark", JSON.toJSONString(claims.values()));
            chain.doFilter(request, response);
            MDC.remove("remark");
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        //初始化动作,比如可以选择那些请求不需要过滤。比如下面获取token的接口
         exceptURLs.add("/api/v4/login/get-token");
    }
}

1.3 H5在请求头中添加了token信息之后发送POST请求获取数据时,总是提示token不能为空。H5端明明已经添加了token信息为什么在我的token验证的方法里面总是会提示token为空呢?

    public static Claims verifyToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String token = request.getHeader(KEY.TOKEN);
        if (StringUtils.isEmpty(token)) {
        	sendJson(response, JSONObject.toJSONString(ResultUtils.returnError("token不能为空,请重新获取",2)));
        	return null;
        }
        Claims claims = JwtUtil.parseJWT(token);
        if (null == claims) {
        	sendJson(response, JSONObject.toJSONString(ResultUtils.returnError("token信息过期,请重新获取",2)));
        	return null;
        }
        return claims;
    }
    
    public static void sendJson(HttpServletResponse response, String data) throws IOException {
    	   response.setCharacterEncoding("UTF-8");
         response.setContentType("application/json");
         PrintWriter writer = response.getWriter();
         writer.write(data);
         writer.flush();
         writer.close();
    }

 

2.问题分析

2.1 经过调试发现在真正接收到请求的数据的请求之前还存在一个请求方法为OPTIONS的请求,查资料发现这是一个“复杂请求”。

2.2 浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。只要同时满足以下两大条件,就属于简单请求。

2.2.1 请求方法是以下三种方法之一:

HEAD
GET
POST

2.2.2 HTTP的头信息不超出以下几种字段:

Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

 

3.解决方案

2.1 在接在到H5的预请求的时候直接放行。(当然我们还可以做出一些提示)接下来我们就处理正常的验证token的合法性了,然后根据token是否合法来返回数据或者做出提示。

@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();
        //判断当前请求的接口是否需要检查token的合法性
        if (exceptURLs.contains(path)) {
            chain.doFilter(request, response);
            return;
        }
        //复杂请求的预请求,我们这里是直接放行
        if (httpRequest.getMethod().equals("OPTIONS")) {
            httpResponse.setStatus(HttpServletResponse.SC_OK);
            chain.doFilter(request, response);
        } else {
        //不是预请求并且在我们需要验证token的url中就检查token的合法性
            Claims claims = JwtUtil.verifyToken(httpRequest, httpResponse);
            MDC.put("remark", JSON.toJSONString(claims.values()));
            chain.doFilter(request, response);
            MDC.remove("remark");
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        //初始化动作,比如可以选择那些请求不需要过滤。比如下面获取token的接口
         exceptURLs.add("/api/v4/login/get-token");
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值