一、跨域问题的原因:
1 浏览器的检查
2 跨域
3 XMLHttpRequest请求
二、跨域问题的解决:
1 禁止浏览器检查:
使用dos命令,在启动浏览器的时候,加一个参数:
chrome --disable-web-security --user-data-dir=g:\temp3
2 JSONP:
JSONP是什么:JSONP是一种协议
JSONP解决跨域的时候后台代码需要改变吗:需要。
需要加一个切面:@ControllerAdvice
并且让这个类要继承AbstractJsonpResponseBodyAdvice
并且重写构造方法JsonpAdvice(){
super("callback");
}
JSONP的实现原理:
JSONP的弊端:
服务器需要改动代码
只支持GET
发送的不是XHR请求
3 请求是跨域的与隐藏跨域:
被调用方解决:
服务器端实现:
配置Filter:
1 @Bean 2 public FilterRegistrationBean registerFilter(){ 3 FilterRegistrationBean bean=new FilterRegistrationBean(); 4 bean.addUrlPattern("/*"); 5 bean.setFilter(new CrosFilter()); 6 }
创建一个Filter:
1 public class CrosFilter implements Filter{ 2 @Override 3 public void init(FilterConfig filterConfig) throws ServletException{ 4 } 5 @Override 6 public void doFilter(ServletRequest request,ServletResponse response,FilterChain filterChain)throws IOException, ServletException{ 7 HttpServletResponse res=(HttpServletResponse)response; 8 res.addHeader("Access-Control-Allow-Origin","http://localhost:8081"); 9 res.addHeader("Access-Control-Allow-Methods","GET"); 10 res.addHeader("Access-Control-Allow-Headers","Content-Type"); 11 filterChain.doFilter(request,response); 12 } 13 }
此处的res.addHeader("Access-Control-Allow-Origin","*");可以使用*来表示所有的域,方法也可以使用*来表示所有的方法。
简单请求和非简单请求:
工作中比较常见的【简单请求】:
方法为:GET HEAD POST
请求header里面:无自定义头、Content-Type为以下几种:
text/plain
multipart/form-data
application/x-www-form-urlencoded
工作中比较常见的【非简单请求】:
put,delete方法的ajax请求
发送json格式的ajax请求
带自定义头的ajax请求
OPTIONS预检命令:
OPTIONS预检命令缓存:
res.addHeader(“Access-Control-Max-Age”,”3600”);//表示在一小时内缓存这个OPTIONS信息,不用每次请求都请求两次。
带Cookie的跨域问题:
Origin必须是全匹配,不能使用*,必须指定域名;并且需要在Filter里面增加:
res.addHeader(“Access-Control-Allow-Credentials”,”true”);
带自定义头的跨域问题:
被调用方-Nginx解决方案:
1 配置虚拟文件vhost:在nginx的目录中创建一个文件夹,命名为vhost,并在nginx的配置文件中的最后一行中加入以下代码:include vhost/*.conf,将vhost中的.conf文件加载进来。
2 在vhost文件夹下新建一个文件b.com.conf,使用nginx的语法,在该文件中加入以下内容:
1 server{ 2 listen 80; //监听的端口 3 server_name b.com; 4 location /{ 5 proxy_pass http://localhost:8080/; 6 } 7 }
此时访问b.com便可以代替之前的localhost:8080进行访问。
3 继续在以上文件中添加:
1 location /{ 2 proxy_pass http://localhost:8080/; 3 add_header Access-Control-Allow-Methods *; 4 add_header Access-Control-Max-Age 3600; 5 add_header Access-Control-Allow-Credentials true; 6 7 add_header Access-Control-Allow-Origin $http_origin; 8 add_header Access-Control-Allow-Headers 9 $http_access_control_request_headers; 10 if ($request_method=OPTIONS){ 11 return 200; 12 } 13 }
Apache配置:
1 打开apache根目录下的conf文件夹下的httpd.conf文件,并搜索vhost,解开LoadModule vhost_alias_module modules/mod_vhost_alias.so
2 继续搜索vhost,解开Include conf/extra/httpd-vhosts.conf
3 打开conf文件夹下的extra文件夹下的httpd-vhosts.conf
4 增加一个虚拟主机,复制一份,并且修改为以下内容:
1 <VirtualHost *:80> 2 ServerName b.com 3 ErrorLog "logs/b.com-error.log" 4 CustomLog "logs/b.com-access.log" common 5 ProxyPass / http://localhost:8080/ 6 </VirtualHost>
5 在httpd.conf文件中解开proxy模块:LoadModule proxy_module modules/mod_proxy.so (140行)
6 在httpd.conf文件中解开proxy http模块:LoadModule proxy_http_module modules/mod_proxy_http.so
7 进入apache的bin目录,双击httpd.exe文件,启动apache。
8 在httpd-vhosts.conf文件中增加响应头:
1 <VirtualHost *:80> 2 ServerName b.com 3 ErrorLog "logs/b.com-error.log" 4 CustomLog "logs/b.com-access.log" common 5 ProxyPass / http://localhost:8080/ 6 7 #把请求头的origin值返回到Access-Control-Allow-Origin字段 8 Header always set Access-Control-Allow-Origin "expr=% 9 {req:origin}" 10 11 #把请求头的Access-Control-Request-Headers值返回到Access- 12 Control-Allow-Headers字段 13 Header always set Access-Control-Allow-Headers "expr=% 14 {req:Access-Control-Request-Headers}" 15 16 Header always set Access-Control-Allow-Methods "*" 17 Header always set Access-Control-Max-Age "3600" 18 Header always set Access-Control-Allow-Credentials "true" 19 20 #处理预检命令OPTIONS,直接返回204 21 RewriteEngine On 22 RewriteCond %{REQUEST_METHOD} OPTIONS 23 RewriteRule ^(.*)$ "/"[R=204,L] 24 </VirtualHost>
9 在httpd.conf文件中,解开headers模块:LoadModule headers_module modules/mod_headers.so
10 在httpd.conf文件中,打开rewrite模块:LoadModule rewrite_module modules/mod_rewrite.so
Spring框架的跨域解决:
在控制器中使用@CrossOrigin注解
调用方解决-隐藏跨域:
1 在hosts文件中,增加一个虚拟域名:127.0.0.1 b.com a.com
2 在nginx的vhosts文件夹中新建一个a.com.conf,打开:
1 server{ 2 listen 80; 3 server_name a.com; 4 l ocation /{ 5 proxy_pass http://localhost:8081/; 6 } 7 location /ajaxserver{ 8 proxy_pass http://localhost:8080/test/; 9 } 10 }