上面的意思就是 你訪問一個什么地址被CORS 協議阻止, 沒有 在Hearder 里面發現 Access-Control-Allow-Origin 的參數的 資源
跨域問題的原因:瀏覽器出於安全考慮,限制訪問本站點以為的資源。
比如你有一個 網站 127.0.0.1:8080/ , 並且上面掛了一個頁面 ,那么在這個頁面中 ,你只訪問 本站點的 資源不會受到限制,但是你如果訪問其他站點,比如 127.0.0.1:8081 的資源就會受到限制。
備注:暫且把 協議,域名,端口都一樣的叫做同一個站點。
但是 帶有 src 屬性的標簽可以沒有這個 限制,比如 img ,script 等等。
在說說歷史,以前的程序前后端不分離, 頁面 和 請求接口,在同一個 域名同一個端口下面。 所有 瀏覽器認為來源這個 站點的頁面 ,請求的是同一個站點的 接口,那么久會允許。
比如 127.0.0.1:8080/index.html ,請求 127.0.0.1:8080/a/b/c/userLit 接口,這樣是可以的
在說說現在,前后點分離,頁面 和接口一般不是一個程序,這樣就不允許,就會拋出這個異常。
比如前端頁面放在 127.0.0.1:8081/index.html ,后端接口 127.0.0.1:8080/a/b/c/userLit ,這時候端口變了( 前面說了 ,協議,域名作者Ip ,端口 要一樣才算一個站點 ),
證明:
1 條件 我啟動了一個Java 程序 在這地有一個資源test.html 對應地址:http://localhost:8080/WebTest/test2.html
2 我啟動了一個 nginx 端口 80 ,並且在 html 文件夾下面有 test.html 對應地址:http://localhost:80/WebTest/test.html
nginx 配置 :
test.html : 如果這么寫 ,沒用 nginx 的 代理 直接訪問 ,會出 跨域問題。
但是 如果 :動態接口 走nginx 代理就不會出問題
解決辦法:
1 比較老的 比較通用,也比較麻煩的 jsonp
原理 利用 <script src="這里面的地址可以跨域,並且返回的 js 代碼會被 立即執行" ></script>
這樣 只要定義一個回調方法f( data ){ 處理數據 },然后 src 對應的接口需要 返回 f( data ); 這樣的 格式,這樣 在 這個數據返回以后就執行了 發f方法,並且帶過來數據。
jquery 之類的 框架 有多這個 封裝,隨時隨地動態的生產 <script> 標簽 ,然后取得數據。
2 后端允許跨域
這個就要看具體怎么部署的了。
1 比如 靜態頁面在有個靜態資源服務 nginx ,那么 就要在后端程序 在響應 Header中也帶上允許跨域的 參數。
備注:跨域的時候,其實接口是有請求的,而且也請求成功返回了,只是 前端瀏覽器認為這個有安全問題,所以不顯示給前端,如果你設置這幾個頭,就認為你服務器允許跨域,會顯示。
2 如果 靜態資源在 nginx中 ,並且前端 沒有直接訪問 后端 接口,而是 nginx 代理 了后端接口,前端總是請求的 ngxin ,因為 這樣就是同一個域名了不會跨域。重點是前端不會直接請求后端,而是通過 nginx代理請求的后端。,並且這個代理 是通過 端口后面的 地址區分,不是通過 端口區分。
比如 nginx 端口 80 ,ip:80/html 指向 靜態資源,ip:80/api 指向 接口服務器。
備注:
Java 后端跨域的設置,具體看你用的什么框架,原理都一樣,在 response 里面寫點東西。
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
|
import
org.springframework.core.annotation.Order;
import
javax.servlet.*;
import
javax.servlet.annotation.WebFilter;
import
javax.servlet.http.HttpServletResponse;
import
java.io.IOException;
@Order
(
1
)
//重點
@WebFilter
(filterName =
"corsFilter"
, urlPatterns = {
"/*"
})
public
class
CORSFilter
implements
Filter{
@Override
public
void
init(FilterConfig filterConfig)
throws
ServletException {
System.out.println(
"初始化filter=========================="
);
}
@Override
public
void
doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws
IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader(
"Access-Control-Allow-Origin"
,
"*"
);
// 這里最好明確的寫允許的域名
response.setHeader(
"Access-Control-Allow-Methods"
,
"POST, GET, OPTIONS, DELETE, PUT"
);
response.setHeader(
"Access-Control-Max-Age"
,
"3600"
);
response.setHeader(
"Access-Control-Allow-Headers"
,
"Content-Type,Access-Token,Authorization,ybg"
);
filterChain.doFilter(servletRequest, servletResponse);
System.out.println(
"filter=========================="
);
}
@Override
public
void
destroy() {
System.out.println(
"銷毀filter=========================="
);
}
}
|
2 nginx 的 跨域設置。 紅的的那幾行
1
2
3
4
5
6
7
8
9
|
location / {
add_header Access-Control-Allow-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'
;
if
($request_method =
'OPTIONS'
) {
return
204
;
}
}
|
3 在 nginx 代理的 動態資源后面 加 跨域參數無效: