在項目中有遇到「跨域」,so要對跨域有個清楚認識,並對安全知識進行簡單總結javascript
注:php
簡述:
html
跨域:是指a頁面想獲取b頁面資源,若是a、b頁面的協議、域名、端口、子域名不一樣,所進行的訪問行動都是跨域的,而瀏覽器爲了安全問題通常都限制了跨域訪問,也就是不容許跨域請求資源。注意:跨域限制訪問,實際上是瀏覽器的限制。
跨域問題:
1. jsonp能夠解決
2. cors設置Access-Control-Allow-Origin頭
3. nginx解決,搭建一箇中轉nginx服務器,用於轉發請求
前端
出於瀏覽器的同源策略限制。java
同源策略(Sameoriginpolicy)是一種約定,它是瀏覽器最核心也最基本的安全功能,若是缺乏了同源策略,則瀏覽器的正常功能可能都會受到影響。能夠說Web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現。同源策略會阻止一個域的javascript腳本和另一個域的內容進行交互。nginx
同源策略限制了從同一個源加載的文檔或腳本與另外一個源的資源進行交互。這是一個用於隔離潛在惡意文件的重要安全機制。
所謂同源(即指在同一個域)就是兩個頁面具備相同的協議(protocol),主機(host)和端口號(port)
當一個請求url的協議、域名、端口三者之間任意一個與當前頁面url不一樣即爲跨域web
【1】沒法讀取非同源網頁的 Cookie、LocalStorage 和 IndexedDB算法
【2】沒法接觸非同源網頁的 DOMjson
【3】沒法向非同源地址發送 AJAX 請求segmentfault
【1】JSONP
JSONP 是服務器與客戶端跨源通訊的經常使用方法。最大特色就是簡單適用,兼容性好(兼容低版本IE),缺點是隻支持get請求,不支持post請求。
核心思想:網頁經過添加一個<script>元素
,向服務器請求 JSON 數據,服務器收到請求後,將數據放在一個指定名字的回調函數的參數位置傳回來。
<script src="http://test.com/data.php?callback=dosomething"></script>
// 向服務器test.com發出請求,該請求的查詢字符串有一個callback參數,用來指定回調函數的名字
// 處理服務器返回回調函數的數據
<script type="text/javascript">
function dosomething(data){
//處理得到的數據
}
</script>複製代碼
【2】CORS 是處理跨域問題的標準作法
原理:CORS是一個W3C標準,全稱是"跨域資源共享"。它容許瀏覽器向跨源服務器,發出XMLHttpRequest
請求,從而克服了AJAX只能同源使用的限制。它爲Web服務器定義了一種方式,容許網頁從不一樣的域訪問其資源.
CORS系統定義了一種瀏覽器和服務器交互的方式來肯定是否容許跨域請求。 它是一個妥協,有更大的靈活性,但比起簡單地容許全部這些的要求來講更加安全。
實現方法:
CORS須要瀏覽器和服務器同時支持。目前,全部瀏覽器都支持該功能,IE瀏覽器不能低於IE10。整個CORS通訊過程,都是瀏覽器自動完成,不須要用戶參與。對於開發者來講,CORS通訊與同源的AJAX通訊沒有差異,代碼徹底同樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感受。
瀏覽器將CORS請求分紅兩類:簡單請求和非簡單請求。
一、簡單請求:只要同時知足如下兩大條件
(1) 請求方法是如下三種方法之一:
(2)HTTP的頭信息不超出如下幾種字段:
簡單請求:只服務端設置, 在response中加header:Access-Control-Allow-Origin便可,若要帶cookie請求:先後端都須要設置。
response.setHeader("Access-Control-Allow-Origin", *);
注意:*時cookie不會在http請求中帶上
若是須要http請求中帶上cookie,須要先後端都設置credentials,且後端設置指定的origin
response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin"));
response.setHeader("Access-Control-Allow-Credentials", "true"); 複製代碼
2.非簡單請求
非簡單請求的cors請求,會在正式通訊以前,發出一次預檢測請求,返回碼是204,預檢測經過纔會真正發出請求,這才返回200。這裏經過前端發請求的時候增長一個額外的headers來觸發非簡單請求。
// 若是須要http請求中帶上cookie,須要先後端都設置credentials,且後端設置指定的origin
response.setHeader('Access-Control-Allow-Origin', 'http://localhost:9099')
response.setHeader('Access-Control-Allow-Credentials', true)
// 非簡單請求的CORS請求,會在正式通訊以前,增長一次HTTP查詢請求,稱爲"預檢"請求(preflight)
// 這種狀況下除了設置origin,
// 還須要設置Access-Control-Request-Method以及Access-Control-Request-Headers
response.setHeader('Access-Control-Request-Method', 'PUT,POST,GET,DELETE,OPTIONS')
response.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, t')
複製代碼
【3】nginx反向代理
想一下,若是咱們請求的時候仍是用前端的域名,而後有個東西幫咱們把這個請求轉發到真正的後端域名上,不就避免跨域了嗎?這時候,Nginx出場了。
實現原理相似於中間件代理,須要你搭建一箇中轉nginx服務器,用於轉發請求。
使用nginx反向代理實現跨域,是最簡單的跨域方式。只須要修改nginx的配置便可解決跨域問題,支持全部瀏覽器,支持session,不須要修改任何代碼,而且不會影響服務器性能。
實現思路:經過nginx配置一個代理服務器(域名與domain1相同,端口不一樣)作跳板機,反向代理訪問domain2接口,而且能夠順便修改cookie中domain信息,方便當前域cookie寫入,實現跨域登陸。
Nginx轉發的方式彷佛很方便!但這種使用也是看場景的,若是後端接口是一個公共的API,好比一些公共服務獲取天氣什麼的,前端調用的時候總不能讓運維去配置一下Nginx,若是兼容性沒問題(IE 10或者以上),CROS纔是更通用的作法吧。
目的:我加密讓別人來驗,因此是私鑰加簽,公鑰驗籤
數字簽名,簡單來講就是經過提供可鑑別的數字信息驗證自身身份的一種方式。一套數字簽名一般定義兩種互補的運算,一個用於簽名,另外一個用於驗證。即:加簽、驗籤
分別由發送者持有可以表明本身身份的私鑰 (私鑰不可泄露),由接受者持有與私鑰對應的公鑰 ,可以在接受到來自發送者信息時用於驗證其身份。
注意:正常 加密過程: 公鑰加密,私鑰解密。
一、簽名 最根本用途是要可以惟一 證實發送方的身份,防止 中間人攻擊,CSRF
跨域身份僞造
二、基於這一點在諸如 設備認證、 用戶認證、 第三方認證等認證體系中都會使用 簽名算法
加密cookie:A+B+C
一、拼接 byte[ ] content = A+B+C, 經過SHA256簽名,獲得2位驗證碼captcha(第二、4位)
二、對 byte[ ] encrypt = A+B 進行AES128加密
三、組合 captcha+ encrypt,再轉爲string,獲得一個加密串result
四、最後經過 result:c 組合成結果
解密cookie
一、冒號分割,獲取前半段
二、經行base64解密,獲得驗證碼和加密串 captcha+ encrypt
三、用AES128對加密串encrypt 進行解密,獲得加密詳情 A+B
四、對詳情 A+B+C 經過SHA256簽名,獲得2位驗證碼captcha2
五、與第2步的驗證碼 captcha 進行比較,相同,說明cookie正確,即返回詳情
Base64編碼的做用:因爲某些系統中只能使用ASCII字符。Base64就是用來將非ASCII字符的數據轉換成ASCII字符的一種方法。它使用下面表中所使用的字符與編碼。
並且base64特別適合在http,mime協議下快速傳輸數據。
base64其實不是安全領域下的加密解密算法。雖然有時候常常看到所謂的base64加密解密。其實base64只能算是一個編碼算法,對數據內容進行編碼來適合傳輸。雖然base64編碼事後原文也變成不能看到的字符格式,可是這種方式很初級,很簡單。
1.前端安全
2.後端安全