springboot jwttoken ajax请求的时候跨域问题
1 跨域有2种
简单跨域和复杂跨域
复杂跨域比如header中加了Authorization token,复杂跨域时,浏览器会发出一个Optional的请求,先试探一下服务允许不允许。
都可以解决
@Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter{ @Autowired AuthenticationFilter authenticationFilter; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authenticationFilter) // .excludePathPatterns("/**") .addPathPatterns("/vehicle/testToken") // .addPathPatterns("/**") // .addPathPatterns("/**") // .excludePathPatterns("/login") .excludePathPatterns("/swagger-resources/**", "/swagger-resources/configuration/ui", "/swagger-ui.html/**", "/v2/**", "/login");; } @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") .allowedHeaders("*") .maxAge(3600) .allowCredentials(true); } }
以上addCrosMappings中的内容就同事可以解决简单跨域和复杂跨域。
但是关键坑爹的事情来了 通过跨域之后如果写了拦截器,验证token 那么由于optional请求中没有带token会在拦截器处被拦截 返回401,这对这个事情 有以下写法
@Component public class AuthenticationFilter extends HandlerInterceptorAdapter { @Autowired JwtUtil jwtUtil; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if ("OPTIONS".equals(request.getMethod())){//这里通过判断请求的方法,判断此次是否是预检请求,如果是,立即返回一个204状态吗,标示,允许跨域;预检后,正式请求,这个方法参数就是我们设置的post了 response.setStatus(HttpStatus.SC_NO_CONTENT); //HttpStatus.SC_NO_CONTENT = 204 response.setHeader("Access-Control-Allow-Methods", "POST, GET, DELETE, OPTIONS, DELETE");//当判定为预检请求后,设定允许请求的方法 response.setHeader("Access-Control-Allow-Headers", "Content-Type, x-requested-with, Token"); //当判定为预检请求后,设定允许请求的头部类型 response.addHeader("Access-Control-Max-Age", "1"); return true; } // 是否登录 boolean isLogin = false; // 获取请求头 Authorization: Bearer jwtToken final String authHeader = request.getHeader("Authorization"); // 判断是否有token,注意 Bearer 后面有空格 if (authHeader != null && authHeader.startsWith("Bearer ")) { // 截取获取jwtToken final String token = authHeader.substring(7); // 解析 Claims claims = jwtUtil.parseJWT(token); if (claims != null) { if ((Boolean) claims.get("isLogin")) { // 已登录 isLogin = true; } } } if(!isLogin) { response.setContentType("application/json;charset=UTF-8"); response.setStatus(401); response.getWriter().write("未通过身份认证"); } return isLogin; } }
这个写法第一 让optional请求不用经过拦截器被拦截,而且在resopnse中返回了需要的信息 比如允许跨域等 这就解决了问题