Http--跨域请求

在浏览器中,与当前页面不同域名的url是不允许访问的,这是浏览器端的限制,后端设置Access-Control-Allow-Origin为发起发的URL即可,相当于开放给这个URL请求(注意,必须要和浏览器中的URl相同,如请求方为127.0.0.1,Access-Control-Allow-Origin设置为localhost是不行的)
如果是允许多个URL请求,可以在Request中获取URL,判断是否允许请求,如果允许,将该url设置到Access-Control-Allow-Origin的值。如下详细的梳理各个点即解决方案

分为简单请求和非简单请求,如果为简单请求,将请求发送过去,后台会响应,但是数据返回到浏览器的时候,检查Origin字段,发现与当前域名不相同。如果为非简单请求,将会发送一个预请求,method为OPTIONS,检查通过了才会发送正常的请求。
简单请求
方法GET,HEAD,POST
Header:无自定义,Content-Type为以下几种:text/plain、multipart/form-data、application/x-www-form-urlcoded
发送一个简单请求:

$.get("http://127.0.0.1:6001/user/getUserInformation?userId=1",function(data,status){
                console.log(data);
            });

在这里插入图片描述
后台得到了响应,但是浏览器端没有数据响应
浏览器控制台报如下错误:

from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

4.1.2 非简单请求
方法:PUT、delete方法的AJAX请求
发送JSON格式的ajax请求
带自定义头的ajax请求。

$.ajax({
                        type: "POST",
                        contentType: "application/json; charset=utf-8",
                        data:JSON.stringify({"username":"123","password":"123"}),
                        url: "http://127.0.0.1:6001/user/addUserInfo",
                        success: function(result) {
                            console.log(result);`在这里插入代码片`
                        }
                    });

允许方法:GET、HEAD、POST,允许Content-Type:Text/plain、Multipart/form-data、Application/x-www-form-urlencoded
预请求
在这里插入图片描述

from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
the server responded with a status of 403 ()

通过在后台添加预检查命令,根据method为options判断即可解决

@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) resp;
    logger.info("method:"+request.getMethod());
    //允许跨域
    response.setHeader("Access-Control-Allow-Origin","*");
    //告诉请求端,哪些自定义的头字段可以被允许添加
    response.setHeader("Access-Control-Allow-Headers","X-Test-Cors");
    //CORS请求预请求时不允许设置Content-Type,在预请求时告诉请求端可以
    response.setHeader("Access-Control-Allow-Headers","content-type");
    //允许跨域请求的最长时间,指定时间内不需要发送预请求过来。
    response.setHeader("Access-Controller-Max-Age","1000");
    if("OPTIONS".equals(request.getMethod())){
        //跨域请求中的非简单请求发送的预请求特殊处理
        response.setStatus(200);
    }else{
        chain.doFilter(req,resp);
    }
}

设置缓存预检时间,在指定的时间内不需要发送预请求

response.setHeader("Access-Controller-Max-Age","1000");

带Cookie的跨域请求
只能读到本域的Cookie,不能读到其他域的Cookie。
Cookie应该添加到被调用方。如在8080下添加Cookie信息,但是在8081下跨域请求8080的服务。
请求方式:

$.ajax({
    type: "get",
    contentType: "application/json; charset=utf-8",
    url: "http://127.0.0.1:8080/user/getCookie",
    xhrFields:{
        //请求时携带Cookie
        withCredentials:true
    },
    success: function(result) {
        console.log(result);
    }
});

在控制台设置Cookie

document.cookie='cookie1=dema'
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
携带Cookie的跨域需要将Access-Control-Allow-Origin设置为发送请求的域,不能设置为*
如下,在8081下跨域请求8080的接口,在8080的服务端,设置Access-Control-Allow-Origin的值为允许url为8081的源url跨域访问。
/允许跨域
response.setHeader("Access-Control-Allow-Origin","http://127.0.0.1:8081");

然后控制台出现如下的问题:

has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

8080服务端设置如下即可:

response.setHeader("Access-Control-Allow-Credentials","true");

总结:携带Cookie的跨域需要将Access-Control-Allow-Origin设置为发送请求的域,不能设置为*,同时在服务端设置Access-Control-Allow-Credentials为true
如果需要设置所有的请求都能跨域请求,可以通过获取头部的Origin字段然后设置为Access-Control-Allow-Origin的值即可

带自定义头的跨域

Access to XMLHttpRequest at 'http://127.0.0.1:8080/user/getHeader' from origin 'http://127.0.0.1:8081' has been blocked by CORS policy: Request header field x-header2 is not allowed by Access-Control-Allow-Headers in preflight response.

预请求返回的信息不支持自定义的头信息,需要修改Access-Control-Allow-Headers的字段信息,

response.setHeader("Access-Control-Allow-Headers","content-type,x-header1,x-header2");
//不写死的方法,支持所有的自定义的头,根据请求信息,返回
String headers = request.getHeader("Access-Control-Request-Headers");
if(headers!=null){
    response.addHeader("Access-Control-Allow-Headers",headers);
}

跨域请求的Nginx的方案
在这里插入图片描述

server{
	listen 80;
	server_name b.com;
	location /{
		proxy_pass http://localhost:8080/;
		add_header Access-Control-Allow-Methods *;
		add_header Access-Control-Max-Age 3600;
		add_header Access-Control-Allow-Credentials true;
		
		#从请求头中获取,不写死的解决方法
		add_header Access-Control-Allow-Origin $http_origin;
		#预检请求--直接返回200
		if ($request_method = OPTIONS){
			return 200;
		}
	}
}

Spring的解决方案
在类上添加如下注解即可

//跨域请求
@CrossOrigin
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值