Nginx配置跨域问题

标签: Javascript 分类: Javascript 创建时间:2019-09-05 06:22:24 更新时间:2024-11-15 10:49:43

前端跨域问题,一直是一个令人头疼的问题。一般的解决方式是使用代理文件,如 c# 的 proxy.ashx文件;或者是直接使用nginx进行转发;最后一种是是设置http的返回头为:Access-Control-Allow-Origin:’*’。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
server {
listen 80;
server_name zhenglc.dev.proheng.net;
root /home/zhenglc/proj/PhEMSTp;
index index.php index.html index.htm;

#access_log logs/host.access.log main;

location /pipelinerealdata{
proxy_pass http://ecs1.proheng.net:9980/CalcPipeInstant;
}

location / {
if (!-e $request_filename){
rewrite ^/(.*)$ /index.php?s=/$1 last;
}
}

location ~ \.(php|html)$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi.conf;
}
}

如果同事设置了两种方式,比如同事设置了header和用了nginx转发,会出现错误:”he ‘Access-Control-Allow-Origin’ header contains multiple values ‘*, *’, but only one is allowed. Origin ‘http://dev.proheng.net‘ is therefore not allowed access.”

这个时候可以取消nginx代理,或者是去掉header一个就可以了。去掉nginx中的

2.情况二

今天开发前端时,出现了奇怪的问题(说的好像,还有不奇怪的问题是的),我在一个页面中同时发送两个ajax请求,第一个请求验证通过了,在后台设置了cookie,第二个请求进入后台相同的方法,会获取用户session,但是第一次设置的session在第二次请求时却丢失了,获取不到。

在前端增加了withCredentials属性,携带cookie之后,后端出现了错误:Access to XMLHttpRequest at ‘http://dev.proheng.net/PhRecruitAdmin/checkLogin?sessionId=‘ 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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$.ajax({
url: path,
data: data,
type: type,
// contentType : 'multipart/json',
dataType : 'json',
xhrFields: {
withCredentials: true
},
beforeSend: function (XMLHttpRequest) {
// XMLHttpRequest.setRequestHeader("openid",vue.$store.state.userinfo.opendid);
},
//headers可以不用放里面的,你的ajax请求需要什么你就应该放到对应的位置
headers: {
"Content-Type":meth ,
// "programId":"manager"//此处放置请求到的用户token
},
success: function (res) {
//可以console.log(res) 看下你的结果
if (!fnSuccess) return false;
if (res.status == 500){

};
if (res) {
fnSuccess(res);
}
},
error: function (e) {
console.log('错误码:'+e.status+';'+'错误信息:'+e.statusText);
//error(e);
},
async : true,
});

后端nginx中也配置了

1
2
3
4
5
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With,Origin,Content-Type;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS,;
add_header Access-Control-Allow-Credentials true;

还是不行:

参考文章中多出强调:

    需要注意的是,如果要发送Cookie,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名。同时,Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie也无法读取服务器域名下的Cookie。

    如果跨域需要携带cookie去请求,Access-Control-Allow-Credentials必须为true,但是需要注意当Access-Control-Allow-Credentials=true时,Access-Control-Allow-Origin就不能为” * “ ,必须是明确的域名,当然可以多个域名使用 “,” 分割

只有把add_header Access-Control-Allow-Origin *;改为 add_header Access-Control-Allow-Origin http://localhost:8080; 这样的确定的域名,才能正确的请求。

3.Access-Control-Allow-Origin 跨域设置多域名

我设置了Access-Control-Allow-Origin多个域名

但是实际上,还是出错了:from origin ‘http://localhost:8080‘ has been blocked by CORS policy: The ‘Access-Control-Allow-Origin’ header contains multiple values

最后解决方法,设置一个变量$cors_origin,存储白名单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
## 设置跨域白名单
set $cors_origin "";
if ($http_origin ~* "^http://bibichuan.github.com ") {
set $cors_origin $http_origin;
}

if ($http_origin ~* "^http://localhost") {
set $cors_origin $http_origin;
}
if ($http_origin ~* "github.com") {
set $cors_origin $http_origin;
}

location ^~/PhRecruitAdmin {
client_max_body_size 40m;

proxy_pass http://localhost:8080/$request_uri;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;

## 跨域

add_header Access-Control-Allow-Origin $cors_origin;
add_header Access-Control-Allow-Methods "POST, GET, OPTIONS";
add_header Access-Control-Allow-Headers "Origin, Authorization, Accept";
add_header Access-Control-Allow-Credentials true;

}

这样无论是本地localhost,还是远程 http://bibichuan.github.com 域名,都可以进行携带cookie访问了。

还可以使用map的方式定义多个地址,就像参考文章7一样

1
2
3
4
5
6
7
8
9
10
map $http_origin $cors_origin {
default "";
"~^(https?://localhost(:[0-9]+)?)" $1;
"~^(https?://127.0.0.1(:[0-9]+)?)" $1;
"~^(https?://172.10(.[\d]+){2}(:[0-9]+)?)" $1;
"~^(https?://192.168(.[\d]+){2}(:[0-9]+)?)" $1;
}
server{

}

注意
如果配置了nginx之后,重启nginx之后,还是提示跨域,尝试清空浏览器缓存试一下。

3.虽然设置了跨域,但是某些请求,还是无法有请求头

今天遇到的奇怪问题,就是我无论怎么配置nginx总是会出现跨域问题。就是感觉有些路径nginx增加了跨域,有些没有,不知道怎么回事。

解决方法就是增加一个always选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
## 设置跨域白名单
set $cors_origin "";
if ($http_origin ~* "^http://dev.proheng.net") {
set $cors_origin $http_origin;
}
if ($http_origin ~* "^http://localhost") {
set $cors_origin $http_origin;
}

## 跨域

add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Methods "POST, GET, OPTIONS" always;
add_header Access-Control-Allow-Headers "Origin, Authorization, Accept" always;
add_header Access-Control-Allow-Credentials true always;

if ($request_method = 'OPTIONS') {
return 204;
}

参考文章:
1.nginx 配置add_header ‘Access-Control-Allow-Origin’ ‘*’ 依然存在跨域问题 (这里有一个就是提供了一个always选项)
2.Nginx配置跨域访问 (这里就是通俗的nginx跨域配置)
3.Nginx配置跨域请求 Access-Control-Allow-Origin * (这里就是通俗的nginx跨域配置)
4.nginx返回错误状态码401 (这个没啥用)
5.nginx 配置 cros 跨域以及遇到 401、500 响应的问题 (这个估计有点用)

4.出现了Access-Control-Allow-Origin请求头丢失的问题

今天使用nginx配置了跨域,奇怪的问题就出现了,同样的配置,同样的请求,一个接口中回出现Access-Control-Allow-Origin请求头,另一个接口中Access-Control-Allow-Origin请求头就丢失了,最后报:Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

奇怪就奇怪在,为什么都是同样的配置,会出现不一样的返回结果呢?

你猜怎么着,还真是我的请求地址写错了,我原本以为是一样的,结果是不一样的。

小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。