【安全系列之跨域】跨域解决方案
一、為什么會出現跨域問題
出于瀏覽器的同源策略限制。同源策略是一種約定,由Netscape公司1995年引入瀏覽器,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到XSS、CSFR等攻擊。所謂同源是指"協議+域名+端口"三者相同,即便兩個不同的域名指向同一個ip地址,也非同源。
二、什么是跨域
當一個請求url的協議、域名、端口三者之間任意一個與當前頁面url不同即為跨域,舉幾個例子:
三、非同源限制
【1】無法讀取非同源網頁的 Cookie、LocalStorage 和 IndexedDB
【2】無法接觸非同源網頁的 DOM
【3】無法向非同源地址發送 AJAX 請求
四、跨域解決方法
跨域大致可以分為三種解決方案:
不建議在前端利用什么 JSONP,iframe+domain 等來實現跨域請求,這種本質是繞過了欺騙了瀏覽器,起不到安全防護的作用。所以我們主要從服務端或者代理入手。
跨域請求究竟發出去沒有?
跨域并不是請求發不出去,請求能發出去,服務端能收到請求并正常返回結果,只是結果被瀏覽器攔截了。你可能會疑問明明通過表單的方式可以發起跨域請求,為什么 Ajax 就不會?因為歸根結底,跨域是為了阻止用戶讀取到另一個域名下的內容,Ajax 可以獲取響應,瀏覽器認為這不安全,所以攔截了響應。但是表單并不會獲取新的內容,所以可以發起跨域請求。同時也說明了跨域并不能完全阻止 CSRF,因為請求畢竟是發出去了。
CORS
目前標準的跨域解決方案是CORS,CORS 是跨域資源分享(Cross-Origin Resource Sharing)的縮寫。它是 W3C 標準,屬于跨源 AJAX 請求的根本解決方法。(有人容易將CORS和跨域劃等號,其實他們一個是問題一個是解決方案)
它的實現則主要在服務端,它通過一些 HTTP Header 來限制可以訪問的域,例如頁面 A 需要訪問 B 服務器上的數據,如果 B 服務器上聲明了允許 A 的域名訪問,那么從 A 到 B 的跨域請求就可以完成。對于那些會對服務器數據產生副作用的 HTTP 請求,瀏覽器會使用OPTIONS 方法發起 一個預檢請求(preflight request),從而可以獲知服務器端是否允許該跨域請求,服務器端確認允許后,才會發起實際的請求。在預檢請求的返回中,服務器端也可以告知客戶端是否需要身份認證信息。我們只需要設置響應頭,即可進行跨域請求。主要是服務器端設置Access-Control-Allow-Origin頭
*CORS 和前端沒什么關系,但是標準的CORS請求不對cookies做任何事情,既不發送也不改變。想要傳遞cookie,需要客戶端與服務端共同設置
1、普通跨域請求:只需服務器端設置Access-Control-Allow-Origin
2、帶cookie跨域請求:前后端都需要進行設置,當需要傳遞cookie時,Access-Control-Allow-Origin 不能設置為 * 號,必須為具體的一個域名。同時,服務端需要設置 Access-Control-Allow-Credentials 為 true。表示服務端同意發送cookie。客戶端需要設置Ajax請求屬性withCredentials=true,讓Ajax請求都帶上Cookie
【前端設置】根據xhr.withCredentials字段判斷是否帶有cookie
①原生ajax
③vue-resource
Vue.http.options.credentials = true④ axios
axios.defaults.withCredentials = true【服務端設置】
服務器端對于CORS的支持,主要是通過設置Access-Control-Allow-Origin來進行的。如果瀏覽器檢測到相應的設置,就可以允許Ajax進行跨域的訪問。
① Java后臺
② 如果你的SpringBoot版本在2.0以上,以下代碼配置即可完美解決你的前后端跨域請求問題:
@Configuration public class CorsConfig {@Beanpublic CorsFilter corsFilter() {final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();final CorsConfiguration corsConfiguration = new CorsConfiguration();/*是否允許請求帶有驗證信息*/corsConfiguration.setAllowCredentials(true);/*允許訪問的客戶端域名* 這里最好不要寫*/corsConfiguration.addAllowedOrigin("*");/*允許服務端訪問的客戶端請求頭*/corsConfiguration.addAllowedHeader("*");/*允許訪問的方法名,GET POST等*/corsConfiguration.addAllowedMethod("*");urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);return new CorsFilter(urlBasedCorsConfigurationSource);} }③@CrossOrigin注解
這個方法僅對Java有用。springboot中,在Controller類上添加一個 @CrossOrigin(origins ="*") 注解就可以實現對當前controller 的跨域訪問了,當然這個標簽也可以加到方法上,或者直接加到入口類上對所有接口進行跨域處理,注意這個注解只在JDK1.8版本以上才起作用。
這個注解有些坑,對于復雜請求可能會有問題,參考方案
https://blog.csdn.net/weixin_40910372/article/details/105126261
代理
webpack本地代理
在webpack.config.js中利用 WebpackDevServer 配置本地代理,詳情配置查看devServer,如下簡單配置案例,這樣 http://localhost:8080/api/getUser.php 的請求就是后端的接口 http://192.168.25.20:8088/getUser.php
【6】websocket
Websocket 是 HTML5 的一個持久化的協議,它實現了瀏覽器與服務器的全雙工通信,同時也是跨域的一種解決方案。WebSocket 和 HTTP 都是應用層協議,都基于 TCP 協議。但是 WebSocket 是一種雙向通信協議,在建立連接之后,WebSocket 的 服務器與 客戶端都能主動向對方發送或接收數據。同時,WebSocket 在建立連接時需要借助 HTTP 協議,連接建立好了之后 client 與 server 之間的雙向通信就與 HTTP 無關了。
【7】Nginx反向代理
Nginx 實現原理類似于 Node 中間件代理,需要你搭建一個中轉 nginx 服務器,用于轉發請求。
使用 nginx 反向代理實現跨域,是最簡單的跨域方式。只需要修改 nginx 的配置即可解決跨域問題,支持所有瀏覽器,支持 session,不需要修改任何代碼,并且不會影響服務器性能。
我們只需要配置nginx,在一個服務器上配置多個前綴來轉發http/https請求到多個真實的服務器即可。這樣,這個服務器上所有url都是相同的域 名、協議和端口。因此,對于瀏覽器來說,這些url都是同源的,沒有跨域限制。而實際上,這些url實際上由物理服務器提供服務。這些服務器內的 javascript可以跨域調用所有這些服務器上的url。
先下載nginx,然后將 nginx 目錄下的 nginx.conf 修改如下:
server {#nginx監聽所有localhost:8080端口收到的請求listen 8080;server_name localhost;# Load configuration files for the default server block.include /etc/nginx/default.d/*.conf;#localhost:8080 會被轉發到這里#同時, 后端程序會接收到 "192.168.25.20:8088"這樣的請求urllocation / {proxy_pass http://192.168.25.20:8088;}#localhost:8080/api/ 會被轉發到這里#同時, 后端程序會接收到 "192.168.25.20:9000/api/"這樣的請求urllocation /api/ {proxy_pass http://192.168.25.20:9000;}error_page 404 /404.html;location = /40x.html {}error_page 500 502 503 504 /50x.html;location = /50x.html {} }寫在最后:
不推薦的最后手段,前端解決跨域的9種方案:
https://www.imooc.com/article/291931
參考資料:
https://blog.csdn.net/weixin_44862325/article/details/105605091?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_title~default-1.pc_relevant_paycolumn_v3&spm=1001.2101.3001.4242.2&utm_relevant_index=3
https://blog.csdn.net/weixin_40910372/article/details/100068498?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164525961416780274141457%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=164525961416780274141457&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-1-100068498.pc_search_insert_ulrmf&utm_term=%E5%90%8E%E7%AB%AF%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3%E8%B7%A8%E5%9F%9F%E9%97%AE%E9%A2%98&spm=1018.2226.3001.4187
總結
以上是生活随笔為你收集整理的【安全系列之跨域】跨域解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 贪心思想草稿
- 下一篇: 【安全系列之XSS】XSS攻击测试以及防