JSON跨域問題總結

一、跨域問題的原因:
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:
@Bean
public FilterRegistrationBean registerFilter(){
FilterRegistrationBean bean=new FilterRegistrationBean();
bean.addUrlPattern("/*");
bean.setFilter(new CrosFilter());
}
創建一個Filter:
public class CrosFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException{
}
@Override
public void doFilter(ServletRequest request,ServletResponse response,FilterChain filterChain)throws IOException, ServletException{
HttpServletResponse res=(HttpServletResponse)response;
res.addHeader("Access-Control-Allow-Origin","http://localhost:8081");
res.addHeader("Access-Control-Allow-Methods","GET");
res.addHeader("Access-Control-Allow-Headers","Content-Type");
filterChain.doFilter(request,response);
}
}
此處的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的語法,在該文件中加入以下內容:
server{
listen 80; //監聽的端口
server_name b.com;
location /{
proxy_pass http://localhost:8080/;
}
}
此時訪問b.com便可以代替之前的localhost:8080進行訪問。
3 繼續在以上文件中添加:
location /{
proxy_pass http://localhost:8080/;
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Max-Age 3600;
add_header Access-Control-Allow-Credentials true;


add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Headers $http_access_control_request_headers;
if ($request_method=OPTIONS){
return 200;
}
}
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 增加一個虛擬主機,複製一份,並且修改爲以下內容:
<VirtualHost *:80>
ServerName b.com
ErrorLog "logs/b.com-error.log"
CustomLog "logs/b.com-access.log" common
ProxyPass / http://localhost:8080/
</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文件中增加響應頭:
<VirtualHost *:80>
ServerName b.com
ErrorLog "logs/b.com-error.log"
CustomLog "logs/b.com-access.log" common
ProxyPass / http://localhost:8080/

#把請求頭的origin值返回到Access-Control-Allow-Origin字段
Header always set Access-Control-Allow-Origin "expr=%{req:origin}"

#把請求頭的Access-Control-Request-Headers值返回到Access-Control-Allow-Headers字段
Header always set Access-Control-Allow-Headers "expr=%{req:Access-Control-Request-Headers}"

Header always set Access-Control-Allow-Methods "*"
Header always set Access-Control-Max-Age "3600"
Header always set Access-Control-Allow-Credentials "true"

#處理預檢命令OPTIONS,直接返回204
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ "/"[R=204,L]
</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,打開:
server{
listen 80;
server_name a.com;
location /{
proxy_pass http://localhost:8081/;
}
location /ajaxserver{
proxy_pass http://localhost:8080/test/;
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章