1. 程式人生 > 其它 >資料結構 - AVL 樹

資料結構 - AVL 樹

基礎知識

1. 同源問題

瀏覽器安全解決方案,對於服務端來說就是限制跨域請求本伺服器資源

2.CORS 跨域資源共享

跨域訪問資源解決方案,瀏覽器與伺服器遵循一定規則,實現跨域資源訪問與共享

a. 資源跨域訪問

b. Cookie 共享

3.相關概念

origin:

請求頭,用於標識請求來源。跨域請求和post請求會攜帶origin請求頭;獲取不到為null

簡單請求:

Cors規範定義簡單請求的原則是:請求不是以更新(新增、修改和刪除)資源為目的,服務端對請求的處理不會導致自身維護資源的改變。對於簡單跨域資源請求來說,瀏覽器將兩個步驟(取得授權和獲取資源)合二為一,由於不涉及到資源的改變,所以不會帶來任何副作用。

對於一個請求,必須同時符合如下要求才被劃為簡單請求:

Http Method只能為其一:
GET
POST
HEAD
請求頭只能在如下範圍:
Accept
Accept-Language
Content-Language
Content-Type,其中它的值必須如下其一:
application/x-www-form-urlencoded
multipart/form-data
text/plain
除此之外的請求都為非簡單請求(也可稱為複雜請求)。非簡單請求可能對服務端資源改變,因此Cors規定瀏覽器在發出此類請求之前必須有一個“預檢(Preflight)”機制,這也就是我們熟悉的OPTIONS請求。

請求預檢:

顧名思義,它表示在瀏覽器發出真正請求之前,先發送一個預檢請求,這個在Http裡就是OPTIONS

請求方式。這個請求很特殊,它不包含主體(無請求引數、請求體等),主要就是將一些憑證、授權相關的輔助資訊放在請求頭裡交給伺服器去做決策。因此它除了攜帶Origin請求頭外,還會額外攜帶如下兩個請求頭:

Access-Control-Request-Method:真正請求的方法
Access-Control-Request-Headers:真正請求的自定義請求頭(若沒有自定義的就是空唄)
服務端在接收到此類請求後,就可以根據其值做邏輯決策啦。如果允許預檢請求通過,返回個200即可,否則返回400或者403唄。

如果預檢成功,在響應裡應該包含上文提到的響應頭Access-Control-Allow-Origin和Access-Control-Expose-Headers,除此之外,服務端還可以做更精細化的控制,這些精細化控制的響應頭為:

Access-Control-Allow-Methods:允許實際請求的Http方法(們)
Access-Control-Allow-Headers:允許實際請求的請求頭(們)
Access-Control-Max-Age:允許瀏覽器快取此結果多久,單位:秒。有了快取,以後就不用每次請求都發送預檢請求啦

說明:以上響應頭並不是必須的。若沒有此響應頭,代表接受所有

Cookie的生命週期:

預設情況下,Cookie的生命週期是Session級別(會話級別)。若想用Cookie進行狀態儲存、資源共享,服務端一般都會給其設定一個過期時間maxAge,短則1小時、1天,長則1星期、1個月甚至永久,這就是Cookie的生命(週期)。

Cookie的儲存形式,根據其生命週期的不同而不同。這由maxAge屬性決定,共有這三種情況:

maxAge > 0:cookie不僅記憶體裡有,還會持久化到硬碟,也叫持久Cookie。這樣的話即使你關機重啟(甚至過幾天再訪問),這個cookie依舊存在,請求時依舊會攜帶
maxAge < 0:一般值為-1,也就臨時Cookie。該Cookie只在記憶體中有(如session級別),一旦關閉瀏覽器此Cookie將不復存在。值得注意的是:若使用無痕模式訪問也是不會攜帶此Cookie的喲
maxAge = 0:記憶體中沒有,硬碟中也沒有了,也就立即刪除Cookie。此種case存在的唯一目的:服務瀏覽器可能的已存在的cookie,讓其立馬失效(消失)

Cookie的域和路徑

Cookie是不可以跨域的,隱私安全機制禁止網站非法獲取其他網站(域)的Cookie。概念上咱不用長篇大論,舉個例子你應該就懂了:

domain:建立此cookie的伺服器主機名(or域名),服務端設定。但是不能將其設定為伺服器所屬域之外的域(若這都允許的話,你把Cookie的域都設定為baidu.com,那百度每次請求豈不要“累死”)
注:埠和域無關,也就是說Cookie的域是不包括埠的
path:域下的哪些目錄可以訪問此cookie,預設為/,表示所有目錄均可訪問此cookie

3. CORS解決方案

1. 簡單請求

response 響應頭新增: Access-Control-Allow-Origin:* 或請求源地址

2. 非簡單請求

瀏覽器傳送預檢 option 請求,伺服器在響應頭中新增

protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    super.doOptions(req, resp);
    resp.setHeader("Access-Control-Allow-Origin","http://localhost:63342");
    resp.setHeader("Access-Control-Expose-Headers","token,secret"); // 如果請求中需要包含標準請求頭以外的請求頭,需要進行配置
    resp.setHeader("Access-Control-Allow-Headers","token,secret"); // 一般來講,讓此頭的值是上面那個的【子集】(或相同)
}

*注意*: 跨域響應頭在預檢請求和真實請求中都需要新增

3. cookie 共享

cookie的共享在於同一根域下的共享

三個關鍵詞:跨域、Cookie、共享。Cookie是資料載體,跨域是場景,共享是需求  

說明:Cookie實現跨域共享要求根域必須是一樣才行,比如都是www.baidu.com和map.baidu.com的根域都是 baidu.com。這道理就相當於只有加入了銀聯的銀行才能用銀行卡去任意一家銀聯成員行取錢一樣

跨域Cookie共享的關鍵點
這裡要討論的是跨域中Cookie的儲存問題:預設情況下,瀏覽器是不會去為你儲存下跨域請求響應的Cookie的。具體現象是:跨域請求的Response響應了即使有Set-Cookie響應頭(且有值),瀏覽器收到後也是不會儲存此cookie的。

要實現Cookie的跨域共享,有3個關鍵點:

服務端負責在響應中將Set-Cookie發出來(由Access-Control-Allow-Credentials響應頭決定)
瀏覽器端只要響應裡有Set-Cookie頭,就將此Cookie儲存(由非同步物件的withCredentials屬性決定)
瀏覽器端發現只要有Cookie,即使是跨域請求也將其帶著(由非同步物件的withCredentials屬性決定)

為了滿足這三個關鍵點,在實施層面就有三要素來指導我們開發來解決此類問題。

共享Cookie的三個要素

1. 跨域情況下伺服器設定了set-cookie也不會生效,需要新增響應頭:

response.setHeader("Access-Control-Allow-Credentials", "true");

2.跨域情況下,伺服器成功設定cookie,瀏覽器預設也不會儲存跨域cookie

XMLHttpRequest物件開啟withCredentials

$.ajax({
    url: "http://localhost:8080/corscookie",
    type: "GET",
    xhrFields: {
        withCredentials: true
    },
    crossDomain: true
});

3. 共享cookie時,請求頭 Access-Control-Allow-Origin 不能為萬用字元