接口跨域问题。后端项目没有配置确切跨域的域名,导致前端访问时即使带上不同的域也能进行访问,具有安全隐患。由于项目太多,在每个项目中添加域名限制有点太过繁琐,所以考虑在nginx中设置禁止跨域。此方案也可用来做自己的小项目的防盗链。
使用nginx的map方法设置
一、局部设置
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
map $http_orgin $allow_cros {
default 1;
"~^(https?://(localhost)(:[0-9]+)?)$" 1;
"~*" 0;
}
server {
listen 8180;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /index {
if ($allow_cros = 0){
return 403;
}
proxy_pass http://localhost:8080/accusation;
}
}
浏览器访问
正常。
模拟跨域访问
-
使用本地域名localhost
能够正常访问。
-
使用www.baidu.com域名进行访问
访问资源失败。没有权限。
二、全局配置
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
map $http_orgin $allow_cros {
default 1;
"~^(https?://(localhost)(:[0-9]+)?)$" 1;
"~*" 0;
}
server {
listen 8180;
if ($allow_cros = 0){
return 403;
}
location / {
root html;
index index.html index.htm;
}
location /index {
proxy_pass http://localhost:8080/accusation;
}
location /accusation {
proxy_pass http://localhost:8080/accusation;
}
}
把if条件语句放到server下面就可以了。
测试结果和上述一致,已经达到预期效果
三、配置指定的localtion正则匹配路径禁止跨域
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
map $http_orgin $allow_cros {
default 1;
"~^(https?://(localhost)(:[0-9]+)?)$" 1;
"~*" 0;
}
server {
listen 8180;
if ($request_uri ~ ^accu.*$){
set $allow_cros "2$allow_cros"
}
if ($allow_cros = "21"){
return 403;
}
location / {
root html;
index index.html index.htm;
}
location /index {
proxy_pass http://localhost:8080/accusation;
}
location /accusation {
proxy_pass http://localhost:8080/accusation;
}
}
-
/index正常访问
-
/accusation拒绝访问
-
/accusation并且域名为"http://localhost:8180"
正常访问。
问题总结
-
为什么不使用
map $http_orgin $allow_cros { default 0; "~^(https?://(localhost)(:[0-9]+)?)$" 1; }
然后判断
location /index { if ($allow_cros = 0){ return 403; } }
来控制呢?
答:这样虽然也能实现跨域拦截,但为在浏览器访问本域下的文件时,请求头上不会带上orgin。此时页面就会变成403未授权。所以采用排除法。而nginx的map特性,是从上至下匹配的,如果匹配上该条件,就不会再继续匹配下面的条件。所以此特性可以让我们设置允许域,而
"~*" 0
表明剩下的都是不被允许访问的。 -
location指定的路径为什么不使用 location的正则匹配?
答: 虽然但是,nginx中的location访问顺序是先普通,后正则。也就是说访问"localhost:8081/accusation"时。先进去/accusation去,再进去正则匹配中。location正则匹配就会替换掉普通匹配的内容,页面访问页面变成404。当然,用其它方法可以解决页面404的问题,但是不用location正则还是比较方便的。
(PS:本内容只代表个人探索过程中遇到的问题及观点!仅以记之,方便以后再次遇到此问题能够查找)