您的位置:首页 > 其它

跨域问题的解决办法(针对服务器)

2018-07-25 18:28 99 查看

什么是跨域?

见名知义,跨域就是在一个域下去请求别的域下的资源。那么为什么两个不同域之间访问就有问题呢?因为浏览器的同源策略。
同源策略:同源策略就像一个规定一样,所有支持js的浏览器都会使用这个策略,同源指的是那些要相同呢?域名,协议,端口相同就是同源,所以说即使是localhost去访问127.0.0.1也是跨域。如果js去请求不同域的资源,浏览器会报错,不允许js去访问,有了同源策略,web才变得更加安全。

怎么解决?

1.代理服务器

头一次遇到跨域问题时,我首先想到的就是代理服务器ngnix,原理很简单,前端该怎么请求就怎么请求,通过代理转发到想要请求的服务器上不就行了。
但是这种适合比较通用的,不然每次添加一个新的都要配置重启nginx不是很好。

[code]server{
    listen 8080; #监听端口
    server_name localhost;  #监听域名
    location ^~ /.do {#拦截请求
        proxy_pass http://localhost:10010;#转发地址
    }    
}

2.CORS(Cross-Origin Resource Sharing)

跨域问题的出现困扰了大批敲键盘的,于是web的老大哥w3c提出了跨源资源共享,即CORS,主要通过服务器来实现跨域问题。其实CORS的原理很简单,通过添加特定参数来判断是否允许跨域,什么参数呢?首先浏览器发送请求时,会判断是不是跨域请求,如果是那么会在请求头添加Origin参数,参数值就是发送请求的域,服务器收到请求后,一看是跨域请求,并且含有该参数便允许该请求的访问,并且服务器会在响应头添加Access-Control-Allow-Origin字段,字段值为服务器规定的可以被访问的域,浏览器收到服务器的响应后,一看哦,我在服务器规定的域里边,那我就把服务器给我的返回给敲键盘的吧,这时我们才看到服务器返回的数据。

Request Heades:

[code]Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Content-Length: 72409
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarylk2Lz1ybjysFCiWi
Host: 127.0.0.1:10011
Origin: http://127.0.0.1:8080
Referer: http://127.0.0.1:8080/material/updatepicture/index.do
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36

Response Headers:

[code]Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://127.0.0.1:8080
Content-Type: application/json;charset=UTF-8
Server: Jetty(9.1.0.M0)
Transfer-Encoding: chunked
Vary: Origin

搞明白原理,在细说一下请求,CROS将前端的请求分为简单请求和复杂请求,
简单请求:
请求方法为head,get,post其中一种,并且请求头参数不可超过Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type,
并且Content-Type参数必须是application/x-www-form-urlencoded,multipart/form-data,text/plain三者中的一个。
复杂请求:
不满足简单请求的就是复杂请求(说了好像没说一样),不过对于复杂请求,浏览器在发送请求之前会先发送一个OPTION预检请求,预检请求跟正常请求没有什么差别,不会携带正常请求的数据,那么为什么浏览器会有这个操作呢?就拿跨域来说,假如没有预检请求,一个跨域请求来了,并且服务器也正常跑了自己的代码,然后这时数据库相关的数据更新了,服务器返回响应结果,这时还没问题,此时浏览器收到服务器的响应,一看跨域了,那可不行,我得告诉敲键盘的你跨域了,返回个错误码,我们一看,报错了,赶紧找原因,但此时我们却不知道数据库已经正确更新数据了,这就很为难了,一次错误请求却跑出来了正确的数据,所以这时浏览器如果先发送个预检请求,预检请求不会携带真实数据,如果预检请求成功请求了,此时发送真实请求就不会有上边的问题了。预检请求除了会添加跨域的标识字段(Access-Control-Allow-Origin)外还会添加Access-Control-Allow-Methods字段,告诉服务器我成功请求后真实请求是什么方式的,服务器同样会在响应头中添加Access-Control-Allow-Methods,表示那些方法可以来访问我以及Access-Control-Max-Age,单位是秒,告诉浏览器,我很忙,在这段时间内直接发送真实请求就行了。有了CORS,跨域就很好解决了,原理就是服务器只需在跨域请求添加浏览器需要的参数就行了。

Response Headers:

[code]Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET,HEAD,POST
Access-Control-Allow-Origin: http://127.0.0.1:8080
Access-Control-Max-Age: 1800
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length: 0
Server: Jetty(9.1.0.M0)
Vary: Origin

Request Headers

[code]Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Access-Control-Request-Method: POST
Connection: keep-alive
Host: 127.0.0.1:10011
Origin: http://127.0.0.1:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36


2.1.通过过滤器

[code]@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest httpServletRequest = (HttpServletRequest) request;
    HttpServletResponse httpServletResponse = (HttpServletResponse) response;
    if(!Validation.hasEmptyStr(httpServletRequest.getHeader("Origin"))){
        httpServletResponse.setHeader("Access-Control-Allow-Origin","http://127.0.0.1:8080");// * 代表所有的
    }

    chain.doFilter(request, response);
}

2.2.如果你用的spring版本在4.2或以上的话,恭喜spring已经支持CORS了
2.2.1
通过@CrossOrigin注解,在某个方法添加,则某个方法可被跨域请求,在某个类上添加,表示该类下的方法都可被跨域请求
2.2.2
通过配置文件

[code]<mvc:cors>  
      <mvc:mapping path="/**"  
       allowed-origins="*"  
       allowed-methods="POST, GET, OPTIONS, DELETE, PUT"  
       allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"  
       allow-credentials="true" />  
</mvc:cors>

推荐一个软件PostMan,想知道干嘛的?点

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: