安装使用nginx解决跨域问题

文章目录

    • 了解同源策略
    • windows安装启动nginx
      • 安装
      • 启动
    • nginx常用命令
    • 解决跨域问题
    • 参考

了解同源策略

在前端本地环境在调用第三方接口,常会遇到No 'Access-Control-Allow-Origin' header is present on the requested resource错误,这是因为浏览器的同源策略拒绝了我们的请求。

什么是同源?
如果两个url的协议、域名、端口相同,就称这两个url是同源

比如http://xxx.com:80/index.htmlhttp://xxx.com:80/dir/index.html 是同源,而 https://xxx:80/index.htmlhttp://xxx:80/index.html不同源,因为协议不同。

同源策略主要表现在DOM、Web数据和Web网络三个层面:

  • DOM:限制了来自不同源的js脚本对当前的DOM对象的读和写操作;
  • Web数据:限制了不同源的站点读取当前站点的Cookie、indexDB、LocalStorage等数据。
  • Web网络:不能通过XMLHttpRequest或Fetch进行跨域请求。

同源策略的出发点是好的,保护数据的安全性,但也影响着开发的便利性,给开发者造成困难,比如不能正常访问非同源的第三方网络接口。

在这里插入图片描述

对于网络请求,我们可以用nginx来代理转发接口,避开浏览器同源策略的限制。

windows安装启动nginx

安装

nginx安装配置还是比较简单的,下载解压后就可以正常启动

nginx下载: http://nginx.org/en/download.html

安装使用nginx解决跨域问题_第1张图片

下载后解压存放你想放的目录下,比如我的:

安装使用nginx解决跨域问题_第2张图片

启动

启动nginx有两种方式:

  • 双击根目录nginx.exe
  • cmd命令启动

建议使用cmd命令启动,以管理员身份启动cmd,进入安装目录,执行启动命令start nginx.exe

H:\Program Files (x86)\nginx-1.22.1>start nginx.exe

命令执行后会有黑色窗口一闪而过,是正常现象。

验证是否启动成功,可以通过nginx -v命令查看版本号,或者预览http://localhost是否正常打开:

安装使用nginx解决跨域问题_第3张图片

关于电脑开机自动启动nginx,可以参考这篇,如果只是临时调试用,上面足够用了。

https://blog.csdn.net/xiaojin21cen/article/details/84622517

nginx常用命令

start nginx.exe       ## 启动服务
nginx.exe -s stop	  ## 快速停止服务
nginx.exe -s quit	  ## 优雅的 停止服务

nginx.exe -s reload	  ## 重新加载 配置文件,这命令可以不用停止nginx
nginx.exe -s reopen	  ## 重新打开日志文件

解决跨域问题

由于浏览器的同源策略,在本地调试接口时出现无法访问问题,通过nginx反向代理转发接口就可以正常访问。

nginx反向代理原理

客户端本来可以直接通过HTTP协议访问某网站应用服务器,如果网站管理员在中间加上一个nginx,客户端请求nginx,nginx请求应用服务器,然后将结果返回给客户端,此时nginx就是反向代理服务器。

安装使用nginx解决跨域问题_第4张图片

比如我现在通过XMLHttpRequest请求https://www.wanandroid.com/project/list/1/json

首先在打开nginx.conf文件,在http{...}作用域中配置代理信息。

H:\Program Files (x86)\nginx-1.22.1\conf\nginx.conf

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    # 连接超时时间,服务器会在这个时间过后关闭连接
    keepalive_timeout  65;
    
    # 直接请求nginx也是会报跨域错误的这里设置允许跨域
    # 如果代理地址已经允许跨域则不需要这些, 否则报错(虽然这样nginx跨域就没意义了)
    # 如果客户端设置了withCredentials,Access-Control-Allow-Origin就是设置全通配*,应该设置指定的应用服务名,比如http://localhost:8080
	add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Headers X-Requested-With;
    add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
    
    # srever模块配置是http模块中的一个子模块,用来定义一个虚拟访问主机
    # 可以配置多个srever模块
    server {
        # 监听80端口,可以随意改
        listen       80;
        # 应用服务器的IP或者host
        # 如果是本地服务:localhost或者本机ip
        server_name  localhost;

        # 根路径指到index.html
        location / {
            root   html;
            index  index.html index.htm;
        }
        # localhost/project 的前缀请求会转发到https://www.wanandroid.com
		location /project {
		    # 转发地址
			proxy_pass https://www.wanandroid.com;
		}

        # 重定向错误页面到/50x.html
        location = /50x.html {
            root   html;
        }

    }
}

关于listen端口号的设置,可以随意改,只要不和其他端口号冲突就可以,比如端口号改成1688,那么url请求建议使用本机ip,通过ipconfig命令查看ip,比如是192.168.0.11。配置如下:

 server {
    listen       1688;
    # 使用localhost或192.168.0.11
    server_name  192.168.0.11;
 }
 # 网络请求url改成 http://192.168.0.11:1688/xxxx/yyyy
 # 如果不改listen的情况,默认就是 http://localhost/xxxx/yyyy

关于本机ip和localhost、127.0.0.1的区别,可以参考这篇 https://www.jianshu.com/p/ad7cd1d5be45

每次修改nginx配置后,记得保存然后执行重载命令nginx -v reload才会生效。

前端代码:

// 原本URL: https://www.wanandroid.com/project/list/1/json
// 改成代理服务server_name来请求
let url = "http://localhost/project/list/1/json"
let params = new URLSearchParams()
params.append("cid","294")
let xhr = new XMLHttpRequest()
// xhr.withCredentials = false
xhr.open("GET",url)
xhr.send(params)
xhr.onload = () =>{
  if (xhr.status === 200){
    console.log("resp: "+xhr.response)
  }
}

最后可以正常看到response日志的输出。

注意:在nginx的每一条配置末尾必须加上;,不然会报错nginx: [emerg] unexpected "}"

nginx代理配置重点在location 上,一些常用的配置需求:

localtion / {
    # 所有请求都匹配以下规则
    # 因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求
    # pass_proxy 等其他配置写在这里
}

location = / {
    # 精确匹配 / ,后面带任何字符串的地址都不符合
}

localtion /api {
    # 匹配任何 /api 开头的URL,包括 /api 后面任意的, 比如 /api/getList
    # 匹配符合以后,还要继续往下搜索
    # 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
}

localtion ~ /api/abc {
    # 匹配任何 /api/abc 开头的URL,包括 /api/abc 后面任意的, 比如 /api/abc/getList
    # 匹配符合以后,还要继续往下搜索
    # 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
}

更详细的配置可以参考:https://segmentfault.com/a/1190000002797606

参考

  • https://blog.csdn.net/xiaojin21cen/article/details/84622517
  • https://juejin.cn/post/6844903473163550734#heading-5
  • https://blog.csdn.net/MrLsss/article/details/107454217
  • https://www.jianshu.com/p/d9de7a5c4673
  • https://www.jianshu.com/p/630e2e1ca57f
  • https://stackoverflow.com/questions/19743396/cors-cannot-use-wildcard-in-access-control-allow-origin-when-credentials-flag-i
  • https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials

你可能感兴趣的:(前端,nginx,跨域,同源策略,nginx安装与启动,nginx跨域)