• 一篇文章让你搞懂如何通过Nginx来解决跨域问题


    Nginx跨域实现

      首先大家要搞清楚什么是跨域,为什么会有跨域情况的出现。哪些情况属于跨域?

    跨域:由于浏览器的同源策略,即属于不同域的页面之间不能相互访问各自的页面内容
    :同源策略,单说来就是同协议,同域名,同端口

    URL 说明 是否允许通信
    http://www.a.com/a.js
    http://www.a.com/b.js 同一域名下 允许
    http://www.a.com/lab/a.js
    http://www.a.com/script/b.js 同一域名下不同文件夹 允许
    http://www.a.com:8000/a.js
    http://www.a.com/b.js 同一域名,不同端口 不允许
    http://www.a.com/a.js
    https://www.a.com/b.js 同一域名,不同协议 不允许
    http://www.a.com/a.js
    http://70.32.92.74/b.js 域名和域名对应ip 不允许
    http://www.a.com/a.js
    http://script.a.com/b.js 主域相同,子域不同 不允许
    http://www.a.com/a.js
    http://a.com/b.js 同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问)
    http://www.cnblogs.com/a.js
    http://www.a.com/b.js 不同域名 不允许

    跨域场景

      出于安全考虑(比如csrf攻击),浏览器一般会禁止进行跨域访问,但是因为有时有相应需求,需要允许跨域访问,这时,我们就需要将跨域访问限制打开。
      启动一个web服务,端口是8081
    在这里插入图片描述
      然后再开启一个web服务/前端服务都可以。端口是8082,然后再8082的服务中通过ajax来访问8081的服务,这就不满足同源策略,就会出现跨域问题

    <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
    <html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8">
    </head>
    <body>
    <h2>Hello World!</h2>
    <script type="text/javascript">
        function fun1(){
            var request = new XMLHttpRequest();
            request.open("GET","http://localhost:8081/user/query")
            request.send();
            request.onreadystatechange = function(){
                if(request.status==200 && request.readyState == 4){
                    console.log("响应的结果" + request.responseText)
                }
            }
        }
    </script>
    </body>
        <input type="button" value="跨域调用" onclick="fun1()">
    </html>
    

    在这里插入图片描述

    跨域问题的解决方案

      解决跨域问题的方式也有多种。

    1、前后端结合(JsonP)

      虽然jsonp也可以实现跨域,但是因为jsonp不支持post请求,应用场景受到很大限制,所以这里不对jsonp作介绍。

    2、纯后端方式一(CORS方式)

      CORS 是w3c标准的方式,通过在web服务器端设置:响应头Access-Cntrol-Alow-Origin 来指定哪些域可以访问本域的数据,ie8&9(XDomainRequest),10+,chrom4,firefox3.5,safair4,opera12支持这种方式。

      服务器代理,同源策略只存在浏览器端,通过服务器转发请求可以达到跨域请求的目的,劣势:增加服务器的负担,且访问速度慢。

    在这里插入图片描述

    3.纯后端方式二(Nginx代理方式)【建议这种方式】

      首先配置Nginx的反向代理方式
    在这里插入图片描述

    代理访问正常
    在这里插入图片描述

    8082的服务访问Nginx,出现了跨域问题

    在这里插入图片描述

    Nginx配置跨域解决

    location / {  
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
    
        if ($request_method = 'OPTIONS') {
            return 204;
    }
    proxy_pass http://192.168.12.1:8081;
    } 
    

    解决了跨域问题
    在这里插入图片描述

    参数说明

    Access-Control-Allow-Origin

      服务器默认是不被允许跨域的。给Nginx服务器配置Access-Control-Allow-Origin *后,表示服务器可以接受所有的请求源(Origin),即接受所有跨域的请求。

    Access-Control-Allow-Headers

      是为了防止出现以下错误:

    Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

      这个错误表示当前请求Content-Type的值不被支持。其实是我们发起了"application/json"的类型请求导致的。这里涉及到一个概念:预检请求(preflight request),请看下面"预检请求"的介绍。

    Access-Control-Allow-Methods

      是为了防止出现以下错误:

    Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

    给OPTIONS 添加 204的返回

      是为了处理在发送POST请求时Nginx依然拒绝访问的错误,发送"预检请求"时,需要用到方法 OPTIONS ,所以服务器需要允许该方法。

    预检请求(preflight request)

      跨域资源共享(CORS)标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。
      其实Content-Type字段的类型为application/json的请求就是上面所说的搭配某些 MIME 类型的 POST 请求,CORS规定,Content-Type不属于以下MIME类型的,都属于预检请求
      所以 application/json的请求 会在正式通信之前,增加一次"预检"请求,这次"预检"请求会带上头部信息 Access-Control-Request-Headers: Content-Type:

  • 相关阅读:
    java代码如何快速添加作者描述的注释最好能有详细的图解
    实现ModelDriver接口的功能
    Java Class类以及获取Class实例的三种方式
    java中的clone()
    applicationContext.xml 配置文件的存放位置
    Spring 整合hibernante 错误java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
    Struts2配置问题java.lang.ClassNotFoundException: org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
    第三篇:解析库之re、beautifulsoup、pyquery(转)
    第二篇:请求库之requests,selenium
    爬虫基本原理(转)
  • 原文地址:https://www.cnblogs.com/dengpengbo/p/15171256.html
Copyright © 2020-2023  润新知