axios跨域post问题
先看看我的代码(多余部分省略)
前端代码:
// 跨域请求后端,发送JSON对象
this.$axios.post("/getDataByConfigInfo",{
tableCode:this.tableCode,
xCoordinateRange:this.dateRange,
classification:this.classification,
attributes:this.checkedAttributes
}).then(Response=>{
console.log(Response.data);
})
后端代码:
@CrossOrigin
@RequestMapping(value = "/getDataByConfigInfo",method = RequestMethod.POST)
public List<Object> getDataByConfigInfo(@RequestBody ForSearch forSearch){
System.out.println(forSearch.toString());
// 省略剩余部分代码
return data;
}
由于需要提交JSON对象,则需要通过post的方式利用axios向后端发送json对象,但是前端报错,提示跨域错误,可是在使用axios进行get时却没有问题
原因:
在执行跨域请求时,具体的请求会被分为两种:简单请求和非简单请求
简单请求需要同时满足两个条件:
- 请求方法是以下三种方法之一:GET POST HEAD
- Http的头信息不超出以下几种字段:Accept Accept-Language Content-Language Last-Event-ID Content-Type 只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
由于我的方法是post并且向后端发送的是JSON,所以后端的当前请求被归为非简单请求
以下部分为关键
浏览器对这两种请求的处理是不一样的.
如果是简单请求的话,一次完整的请求过程是不需要服务端预检的,直接响应回客户端,而非简单请求则浏览器会在发送真正请求之前先用OPTIONS发送一次预检请求preflight request,从而获知服务端是否允许该跨域请求,当服务器确认允许之后,才会发起真正的请求.那么前面所出现的异常很明显就是由这个preflight request导致的了,回头看代码可发现我们在发起ajax调用时往请求头里面塞了两个自定义的header参数token和device,所以此次调用属于非简单请求,并触发了一次预检请求,由于我们服务端使用了shiro权限认证框架,通过拦截用户请求头中传过来的token信息来判定客户端是否为非法调用,而Preflight请求过程中并不会携带我们自定义的token信息到服务器,这样服务器校验就永远也无法通过了,就算是合法的登录用户也会被拦截.
解决办法:在后端检测到该请求为预检请求时,不让它继续往下走(也可以返回一个2xx的状态码),直接告诉浏览器此次跨域请求可以继续,很明显过滤器符合我们的要求,我们来把之前的addCorsMappings方法去掉,重写这块代码
在SpringBoot启动类上加入一下部分即可
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public FilterRegistrationBean registration(){
return new FilterRegistrationBean(new Filter() {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String method = request.getMethod();
// this origin value could just as easily have come from a database
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "Accept, Origin, X-Requested-With, Content-Type,Last-Modified,device,token");
if ("OPTIONS".equals(method)) {//检测是options方法则直接返回200
response.setStatus(HttpStatus.OK.value());
} else {
chain.doFilter(req, res);
}
}
public void init(FilterConfig filterConfig) {
}
public void destroy() {
}
});
}
}
本文部分摘自Briseis大佬的文章,以下为原文链接
作者:Briseis 链接:www.jianshu.com/p/1ad4358be… 来源:简书