跨域問題
打開浏覽器檢查頁面會發現沒有輸出伺服器傳回的消息而是,出現了一個錯誤資訊,這就是前後端分離最常見的跨域問題
問題原因
這是因為浏覽器都采用了同源政策,即不允許通路不屬于本伺服器的資源。
同源政策
同源政策(Same origin policy)是一種約定,它是浏覽器最核心也最基本的安全功能,如果缺少了同源政策,則浏覽器的正常功能可能會受到影響。可以說Web是建構在同源政策基礎之上的,浏覽器隻是針對同源政策的一種實作。
同源政策是浏覽器的行為,是為了保護本地資料不被JavaScript代碼擷取回來的資料污染,浏覽器會先發送OPTION請求進行預檢查,判斷伺服器是否允許跨域,如果允許才發送真正的請求,否則抛出異常。
簡單的說:
同源政策是浏覽器的核心安全機制,其不允許在頁面中解析執行來自其他伺服器資料
同源限制
1、不允許通路非同源網頁的Cookie、LocalStorage 和 IndexedDB。
2、不允許向非同源位址發送ajax請求。
如何判斷跨域
當請求的url的協定,域名,端口号三者中任意一個與目前url不同,即為跨域
什麼時候會産生跨域問題
當浏覽器在解析資料時,頁面中js代碼請求了非同源的資源,則會産生跨域問題,當浏覽器直接跳轉到另一個非同源頁面,不會發生跨域問題
跨域解決方法
需要設定浏覽器允許解析跨域請求的資料,但是這個設定必須放在伺服器端,由伺服器端來判斷對方是否可信任
設定接口:
在需要通路的接口的響應頭中添加一個字段,告訴浏覽器,某個伺服器是可信的
其值可以是某個或多個指定的域名,也可以是*表示信任所有位址
//指定允許其他域名通路
'Access-Control-Allow-Origin:http://XXX.XXX.XXX'//一般用法(*,指定域,動态設定),注意*不允許攜帶認證頭和cookies
//預檢查間隔時間
'Access-Control-Max-Age: 1800'
//允許的請求類型
'Access-Control-Allow-Methods:GET,POST,PUT,POST'
//列出必須攜帶的字段
'Access-Control-Allow-Headers:x-requested-with,content-type'
過濾器設定
通過過濾器進行整體設計:
@WebFilter(filterName = "HTTPFilter",urlPatterns = "/*")
public class HTTPFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletResponse response = (HttpServletResponse)resp;
//允許通路的方法:POST,GET
response.setHeader("Access-Control-Allow-Methods","POST,GET");
//設定響應類型為json資料
response.setContentType("application/json;charset=utf-8");
//允許http://127.0.0.1:8848跨域通路,寫死了一般不這樣寫
//response.setHeader("Access-Control-Allow-Origin","http://127.0.0.1:8848");
//動态設定
ArrayList<String> hosts = new ArrayList<String>();
hosts.add("http://127.0.0.1:8848");
HttpServletRequest request = (HttpServletRequest)req;
if (hosts.contains((request.getHeader("Origin")))){
response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
}
chain.doFilter(req, resp);
}
}
cookie跨域
預設情況下cookie是不允許跨域傳輸的.可以通過以下方式來解決
第一步
浏覽器端設定允許cookie跨域
第二步
伺服器端在響應中添加字段,說明允許cookie跨域
該值隻能是true,為false無效,預設為false
跨域問題的解決方案補充
跨域問題除了通過設定header的方式來允許浏覽器進行跨域通路外,也可以通過反向代理來解決跨域問題
代理伺服器
當我們使用了代理後,可以利用代理伺服器來完成請求轉發,即所有請求,都會先發送到代理伺服器,代理伺服器再和真正的伺服器進行互動,而這個互動過程是不會産生有跨域問題産生的
ngin 和node.js等都可以作為代理伺服器
在開發階段通常是使用node+vue來完成環境搭建 上線則使用nginx
強調
因為跨域問題是因為同源政策,而同源政策隻是針對浏覽器的一個政策,即在使用除浏覽器之外的其他任何用戶端請求都不會産生跨域問題
連結:前後端分離狀态保持問題之JWT