跨域的常见问题和解决方案

邱秋 • 2018年12月21日 • 阅读:1477 • javascript

第一种

No 'Access-Control-Allow-Origin' header is present on the requested resource
The response had HTTP status code 404

出现这种情况的原因如下:

  • 本次 ajax 请求是“非简单请求”,所以请求前会发送一次预检请求(OPTIONS)
  • 服务器端后台接口没有允许 OPTIONS 请求,导致无法找到对应接口地址

解决方法

//node
//koa
const Koa = require('koa');
const app = new Koa();
const router = require('./router');

app.use(router.routes());
app.use(router.allowedMethods());

//java
//CorsFilter.java
public class CorsFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest)servletRequest;

        String method = request.getMethod();
        if(method.equalsIgnoreCase("OPTIONS")){ //处理OPTIONS请求
            servletResponse.getOutputStream().write("Success".getBytes("utf-8"));
        }else{
            filterChain.doFilter(servletRequest, servletResponse);
        }
    }

    @Override
    public void destroy() {

    }
}
//web.xml
<filter>
    <filter-name>corsFilter</filter-name>
    <filter-class>xxx.xxx.CorsFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>corsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

第二种

No 'Access-Control-Allow-Origin' header is present on the requested resource The response had HTTP status code 405

原因是接口不允许 会或者缺少 GET,POST 对应的接口暴露,比如 GET 写成了 POST,或者是其他安全策略阻止了访问

第三种

No 'Access-Control-Allow-Origin' header is present on the requested resource status 200

原因是 头部匹配时出现不匹配现象 解决方法

//node
async (ctx, next) => {
    ctx.set({
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept',
        'Access-Control-Allow-Methods': 'PUT,POST,GET,DELETE,OPTIONS',
    });
    ctx.type = 'application/json'
    ctx.body = {code:0}
}

//nginx
server {
    listen       80;
    server_name  www.chuchur.com;
    location / {
        proxy_pass   http://www.chuchur.org;  #反向代理
        index  index.html index.htm;

        # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
        add_header Access-Control-Allow-Origin http://www.chuchur.com;  #当前端只跨域不带cookie时,可为*
        add_header Access-Control-Allow-Credentials true;
    }
}
//java 在Filter 里面加入

String origin = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Origin", origin);
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization");
response.setHeader("Access-Control-Allow-Credentials", "true");

第四种

Request header field x-csrf-token is not allowed by Access-Control-Allow-Headers in preflight response. 原因是客户端头部信息('x-csrf-token')不被后端接收.两边同步下就可以了

第五种

The 'Access-Control-Allow-Origin' header contains multiple values '_, _', but only one is allowed.

出现这个原因是 重复配置了跨域的头部信息导致的, 比如:

//node http://192.168.0.100:7001 node run in 7001
async (ctx, next) => {
    ctx.set({
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept',
        'Access-Control-Allow-Methods': 'PUT,POST,GET,DELETE,OPTIONS',
    });
    ctx.type = 'application/json'
    ctx.body = {code:0}
}

//nginx proxy to nginx 7001
server {
    listen       80;
    server_name  www.chuchur.com;
    location / {
        proxy_pass       http://192.168.0.100:7001; //转发到node的7001
        add_header Access-Control-Allow-Origin *;  //当前端只跨域不带cookie时,可为*
        add_header Access-Control-Allow-Credentials true;
    }
}
//

当客户端通过 nginx 上传图片的时候就会出现这个问题, nodenginx 同时配置了跨域的头部信息

我,秦始皇,打钱!