使用nginx修改接口响应头解决跨域问题
发布日期:2021-10-21文章字数:0.8K
跨域这个问题对于前端来说是老生常谈了,搜索一下相关问题就会出现一堆解决方案,有的方法是通过使用nginx反向代理来解决跨域问题,不过这种方是只存在两个域的情况下,比如说我们的前端页面发布在A服务器上,然后接口是B服务器提供,我们在A服务器上通过nginx反向代理请求B服务器的接口。不过我最近碰到的问题要比这个复杂点,现在我们有三个域,我们多了一个第三方的接口在C服务器上,这个接口是第三方提供,不受控制,而且因为一些原因配置了白名单,只能通过B服务器的ip来访问,这样我们只能把nginx放在B服务器上来转发C服务器的接口。
nginx配置如下
location /Api/ {
proxy_pass http://serverC/Api/;
}
配置好了后,我们可以通过B服务器来访问C服务的接口了,但是浏览器却报了一个错:
Access to XMLHttpRequest at 'http://XXX.com/API' from origin 'http://localhost:8080' has been blocked by CORS policy: 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.
翻译过来就是:在localhost:8080向发起的XMLHttpRequest请求被CORS策略阻止了,当请求的凭证模式为’include’时,响应头’Access-Control-Allow-Origin’的值不能是通配符*,XMLHttpRequest 发起的请求的凭证模式由 withCredentials 属性控制
withCredentials这个属性你可以简单理解为跨域请求是否带cookie,默认是false,这里我们是需要cookie的所以必须设成true,但是设置为true的话,接口返回的响应头’Access-Control-Allow-Origin’的值就不能是*,必须是请求方的地址。在vue项目中,这个值一般在封装axios的代码里:
const service = axios.create({
baseURL: '', // url = base url + request url
withCredentials: true, // 配置跨域请求是否带cookies
timeout: 300000 // request timeout
})
因为这个C服务器的接口不受控制,所以不能通过代码层面来解决,那么能不能使用nginx来修改这个响应头呢,答案是肯定的,查了一些资料并试验后,我成功解决了这个问题,首先我们通过配置proxy_hide_header把C接口的响应头Access-Control-Allow-Origin给去掉,然后再加上一个正确的响应头,来达到修改的效果,具体配置如下:
location /Api/ {
# 配置OPTIONS请求,返回204状态
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Origin $http_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';
return 204;
}
proxy_pass http://serverC/Api/;
proxy_hide_header Access-Control-Allow-Credentials; # 隐藏错误响应头
proxy_hide_header Access-Control-Allow-Origin; # 隐藏错误响应头
add_header Access-Control-Allow-Credentials true; # 添加正确响应头
add_header Access-Control-Allow-Origin $http_origin; # 添加正确响应头
}
配置中除了Access-Control-Allow-Origin还有个Access-Control-Allow-Credentials响应头,这个值也是必须的,而且必须为true,加上上面的配置之后就能愉快地开发了。