<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] # 簡介 前后端分離通過 Restful API 進行數據交互時,如何驗證用戶的登錄信息及權限。 由于 HTTP 協定是不儲存狀態的 (stateless),這意味著當我們透過帳號密碼驗證一個使用者時,當下一個 request 請求時它就把剛剛的資料忘了。于是我們的程序就不知道誰是誰,就要再驗證一次。 所以為了保證系統安全,我們就需要驗證用戶否處于登錄狀態。 # 傳統方式 前端登錄,后端根據用戶信息生成一個 token,并保存這個 token 和對應的用戶 id 到數據庫或 Session 中,接著把 token 傳給用戶,存入瀏覽器 cookie,之后**瀏覽器請求帶上這個 cookie**,后端根據這個 cookie 值來查詢用戶,驗證是否過期。 ## 缺點 1. XSS 漏洞 如果我們的頁面出現了 XSS 漏洞,由于 cookie 可以被 JavaScript 讀取,XSS 漏洞會導致用戶 token 泄露,而作為后端識別用戶的標識,cookie 的泄露意味著用戶信息不再安全。 盡管我們通過轉義輸出內容,使用 CDN 等可以盡量避免 XSS 注入,但誰也不能保證在大型的項目中不會出現這個問題。 其實你**可以設置 httpOnly 以及 secure 項**。 1. 設置 httpOnly 后 cookie 將不能被 JS 讀取,瀏覽器會自動的把它加在請求的 header 當中; 2. 設置 secure 的話,cookie 就只允許通過 HTTPS 傳輸。secure 選項可以過濾掉一些使用 HTTP 協議的 XSS 注入,但并不能完全阻止。 2. 服務器端的壓力 如果將驗證信息保存在數據庫中,后端每次都需要根據 token 查出用戶 id,這就增加了數據庫的查詢和存儲開銷。若把驗證信息保存在 session 中,又加大了服務器端的存儲壓力。 ## 疑問??? httpOnly 選項使得 JS 不能讀取到 cookie,那么 XSS 注入的問題也基本不用擔心了。 但設置 httpOnly 就帶來了另一個問題,就是很容易的被 XSRF,即跨站請求偽造。 當你瀏覽器開著這個頁面的時候,另一個頁面可以很容易的跨站請求這個頁面的內容。因為 cookie 默認被發了出去。 那我們可不可以**不要服務器去查詢呢**? 如果我們生成 token 遵循一定的規律,比如我們使用對稱加密算法來加密用戶 id 形成 token,那么服務端以后其實只要解密該 token 就可以知道用戶的 id 是什么了。不過呢,我只是舉個例子而已,要是真這么做,只要你的對稱加密算法泄露了,其他人可以通過這種加密方式進行偽造 token,那么所有用戶信息都不再安全了。恩,那用非對稱加密算法來做呢,其實現在有個規范就是這樣做的,接下來要介紹的 JWT。 # JWT 介紹 JSON Web Token(縮寫 JWT)是目前最流行的跨域認證解決方案。 它定義了一種簡潔,自包含的用于通信雙方之間以 JSON 對象的形式安全傳遞信息的方法。 JWT 可以使用 HMAC 算法或者是 RSA 的公鑰密鑰對進行簽名。 它具備兩個特點: * 簡潔(Compact) 可以通過 URL,POST 參數或者在 HTTP header 發送,因為數據量小,傳輸速度快 * 自包含(Self-contained) 負載中包含了所有用戶所需要的信息,避免了多次查詢數據庫 # JWT 組成 JWT 的三個部分依次如下: * Header(頭部) * 進行 base64 編碼 * Payload(負載) * 進行 base64 編碼 * 因為 `base64` 是對稱解密的,意味著該部分信息可以歸類為明文信息。 * Signature(簽名) * 將 Header 和 Payload 通過密鑰 secret 和加鹽算法進行加密后生成 寫成一行,就是下面的樣子: ``` Header.Payload.Signature // 示例 Token eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJVc2VySWQiOjEyMywiVXNlck5hbWUiOiJhZG1pbiJ9.Qjw1epD5P6p4Yy2yju3-fkq28PddznqRj3ESfALQy_U ``` 如果你還想確認這些信息是否真的存在,可以拷貝 JWT 串到 http://jwt.io 的在線校驗工具校驗一下即可。 其實到這一步可能就有人會想了,HTTP 請求總會帶上 token,這樣這個 token 傳來傳去占用不必要的帶寬啊。 其實相比 cookie ,token是可選擇的攜帶在 header 頭上; 還有可以去了解下 HTTP2,HTTP2 對頭部進行了壓縮,相信也解決了這個問題。 ![](https://www.wangbase.com/blogimg/asset/201807/bg2018072303.jpg) # JWT 使用 ![](https://img.kancloud.cn/b1/60/b160a315a435dbdc02916b6d8622541c_919x620.png) 1. 首先,前端通過 Web 表單將自己的用戶名和密碼發送到后端的接口。這一過程一般是一個 HTTP POST 請求。建議的方式是通過 SSL 加密的傳輸(https 協議),從而避免敏感信息被嗅探。 2. 后端核對用戶名和密碼成功后,將用戶的 id 等其他信息作為 JWT Payload(負載),將其與頭部分別進行 Base64 編碼拼接后簽名,形成一個 JWT。形成的 JWT 就是一個形同 `hhh.ppp.sss` 的字符串。 3. 后端將 JWT 字符串作為登錄成功的返回結果返回給前端。**前端可以將返回的結果保存在 `localStorage` 或 `sessionStorage` 上,退出登錄時前端刪除保存的 JWT 即可**。 4. 前端在每次請求時將 JWT 放入 HTTP Header 中的 `Authorization` 位。(解決 XSS 和 XSRF 問題) ``` fetch('api/user/1', { headers: { 'Authorization': 'Bearer ' + token // JWT 規定的的表示形式 } }) ``` 5. 后端檢查是否存在,如存在驗證 JWT 的有效性。例如,檢查簽名是否正確;檢查 Token 是否過期;檢查 Token 的接收方是否是自己(可選)。 服務器將用戶信息和自己的密鑰通過既定好的算法進行簽名,然后將發來的簽名和生成的簽名比較,嚴格相等則說明用戶信息沒被篡改和偽造,驗證通過。 6. 驗證通過后后端使用 JWT 中包含的用戶信息進行其他邏輯操作,返回相應結果。 ## 和 Session 方式存儲 id 的差異 Session 方式存儲用戶 id 的最大弊病在于 Session 是存儲在服務器端的,所以需要占用大量服務器內存,對于較大型應用而言可能還要保存許多的狀態。一般而言,大型應用還需要借助一些 KV 數據庫和一系列緩存機制來實現 Session 的存儲。 1. JWT 方式將用戶狀態分散到了客戶端中,可以明顯減輕服務端的 內存壓力。 2. JWT 方式讓服務器有一些計算壓力(例如加密、編碼和解碼),但是這些壓力相比磁盤存儲而言可能就不算什么了。 除了用戶 id 之外,還可以存儲其他的和用戶相關的信息,例如該用戶是否是管理員、用戶所在的分組等。 具體是否采用,需要在不同場景下用數據說話。 ## 單點登錄(SSO) Session 方式來存儲用戶 id,一開始用戶的 Session 只會存儲在一臺服務器上。 對于有多個子域名的站點,每個子域名至少會對應一臺不同的服務器,例如:`www.taobao.com`,`nv.taobao.com`,`nz.taobao.com`,`login.taobao.com`。 所以如果要實現在`login.taobao.com`登錄后,在其他的子域名下依然可以取到 Session,這要求我們在多臺服務器上同步 Session。使用 JWT 的方式則不會存在這個問題,因為用戶的狀態已經被傳送到了客戶端。 # 總結 ## 優點 因為 json 的通用性,所以 JWT 是可以進行跨語言支持的,像 JAVA、JavaScript、NodeJS、PHP 等很多語言都可以使用。 因為有了 payload 部分,所以 JWT 可以在自身存儲一些其他業務邏輯所必須的非敏感信息。 便于傳輸,jwt 的構成非常簡單,字節占用很小,所以它是非常便于傳輸的。 它不需要在服務端保存會話信息,所以它易于應用的擴展。 ## 安全相關 1. 不應該在 jwt 的 payload 部分存放敏感信息,因為該部分是客戶端可解密的部分。 2. 保護好 secret 私鑰,該私鑰非常重要。 3. 如果可以,請使用 https 協議。 # 其他資料 [基于 JWT 的 Token 認證的安全問題](https://www.cnblogs.com/ypppt/p/13332007.html) [基于 Token 的身份驗證](https://ninghao.net/blog/2834) [Vue刷新token,判斷token是否過期、失效的最簡便的方法](https://blog.csdn.net/weixin_40667613/article/details/90639614) # 參考 [通過一個案例理解 JWT](https://juejin.im/post/5ba37c50e51d450e664b3fc3) [前后端分離之 JWT 用戶認證](https://lion1ou.win/2017/01/18/) [前后端分離, 前端如何防止直接輸入 URL 進入頁面?](https://www.zhihu.com/question/269101275) [JSON Web Token 入門教程](https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html) [前后端分離模式下,如何跟蹤用戶狀態?](https://blog.csdn.net/hwhsong/article/details/82020526)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看