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 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.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
2.1 在接在到H5的预请求的时候直接放行。(当然我们还可以做出一些提示)接下来我们就处理正常的验证token的合法性了,然后根据token是否合法来返回数据或者做出提示。
@WebFilter(filterName = "jwtFilter", urlPatterns = "/api/*")
public class JwtFilter implements Filter {
private static Set 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");
}
}