1.概述

上篇讲述了关于跨域的后端解决方案,本文将展示利用反向代理服务器nginx,来解决跨域问题。闲话少说,直接开干!

2.基于Nginx反向代理配置

首先讲一下利用nginx反向代理的原理:前端不直接请求后端服务,而是通过nginx去转发请求,也就是前端请求nginx,在nginx配置中添加允许跨域请求的配置,这样由nginx转发后的请求便能读取到后端服务数据,再返回给前端。流程如下图所示:

nginx 禁止跨域 nginx解决跨域请求详解_Access


本文将基于上文案例进行修改,具体可参考上文:SpringBoot从入门到放弃-跨域问题解决方案,具体修改的内容包括:

  • 1.修改前端代码中请求路径,由直接请求后端服务器转向请求nginx;
  • 2.在nginx中添加配置,将前端该路径下的请求都转向后端指定服务器,并允许跨域;
  • 3.去除后端服务中之前关于跨域部分配置。

2.1 前端代码修改

修改后代码如下:

<template>
  <div class="hello">
    <h1>{{ goods }}</h1>
    <a href="javascript:;" class="btn btn--m" @click="getData()">点我</a>
  </div>
</template>

<script>
  import axios from 'axios'

  export default {
    name: 'HelloWorld',
    data() {
      return {
        msg: 'Hello Marinc',
        goods: null
      }
    },
    methods: {
      getData() {
        axios.get("http://localhost:8090/api/cors/test").then((res) => {
          let result = res.data;
          console.log(result)
          this.goods = result
        })
      },

    }
  }
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
  h1, h2 {
    font-weight: normal;
  }

  ul {
    list-style-type: none;
    padding: 0;
  }

  li {
    display: inline-block;
    margin: 0 10px;
  }

  a {
    color: #42b983;
  }
</style>

2.2 新增nginx配置

location /api {
            proxy_pass   http://127.0.0.1:8095/;
            add_header Access-Control-Allow-Origin *;
            add_header Access-Control-Allow-Methods "GET, POST, PUT, OPTIONS";
        }

2.3 去除后端服务中关于跨域的配置

1.若是以@CrossOrigin注解解决,去除所有该注解,重启服务;
2.若是添加CORS过滤器解决跨域问题,注释或删除所有该过滤器部分代码;
3.若是继承WebMvcConfigurer接口实现addCorsMappings(),去除该部分代码。

2.4 结果验证

nginx 禁止跨域 nginx解决跨域请求详解_nginx_02

3.小结

1.文章主要提供了一种利用nginx来解决跨域问题的方法,这种方法不用大量修改代码,只需在nginx中新增一些配置,同时修改一部分前端代码的请求路径而已,便于系统解耦;
2.nginx是一种较为强大的反向代理服务器,可以做静态文件服务器,也可以用作负载均衡服务器,日常开发中要掌握基础功能的使用。

4.参考文献


5.附录

新增一个关于nginx比较全的解决跨域配置,如下:

server {
    listen 80;
    server_name localhost 127.0.0.1;
	location / {
		# 允许跨域请求的“域”,此处可以填具体域名、地址或通配符*
		add_header 'Access-Control-Allow-Origin' $http_origin always;
		# 允许客户端提交Cookie
		add_header 'Access-Control-Allow-Credentials' 'true';
		# 允许客户端的请求方法
		add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT';
		# 允许客户端提交的的请求头
		add_header 'Access-Control-Allow-Headers' 'Origin, x-requested-with, Content-Type, Accept, Authorization';
		# 允许客户端访问的响应头
		add_header 'Access-Control-Expose-Headers' 'Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma';
		# 处理预检请求
		if ($request_method = 'OPTIONS') {
			# 预检请求缓存时间
			add_header 'Access-Control-Max-Age' 1728000;
			add_header 'Content-Type' 'text/plain; charset=utf-8';
			add_header 'Content-Length' 0;
			return 204;
		}
		
		# 服务端访问路径
		proxy_pass http://127.0.0.1:8080;
		
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;
		
		proxy_connect_timeout 600;
		proxy_read_timeout 600;
	}
}