溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

web開發(fā)中前后端常見的鑒權(quán)方式有哪些

發(fā)布時間:2021-08-11 15:08:50 來源:億速云 閱讀:321 作者:小新 欄目:web開發(fā)

這篇文章主要為大家展示了“web開發(fā)中前后端常見的鑒權(quán)方式有哪些”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“web開發(fā)中前后端常見的鑒權(quán)方式有哪些”這篇文章吧。

目前我們常用的鑒權(quán)有四種:

  1. HTTP Basic Authentication

  2. session-cookie

  3. Token 驗證

  4. OAuth(開放授權(quán))

一.HTTP Basic Authentication

   這種授權(quán)方式是瀏覽器遵守http協(xié)議實現(xiàn)的基本授權(quán)方式,HTTP協(xié)議進(jìn)行通信的過程中,HTTP協(xié)議定義了基本認(rèn)證認(rèn)證允許HTTP服務(wù)器對客戶端進(jìn)行用戶身份證的方法。

認(rèn)證過程:

  1. 客戶端向服務(wù)器請求數(shù)據(jù),請求的內(nèi)容可能是一個網(wǎng)頁或者是一個ajax異步請求,此時,假設(shè)客戶端尚未被驗證,則客戶端提供如下請求至服務(wù)器:

  Get /index.html HTTP/1.0
  Host:www.google.com

  2. 服務(wù)器向客戶端發(fā)送驗證請求代碼401,(WWW-Authenticate: Basic realm=”google.com”這句話是關(guān)鍵,如果沒有客戶端不會彈出用戶名和密碼輸入界面)服務(wù)器返回的數(shù)據(jù)大抵如下:

  HTTP/1.0 401 Unauthorised
  Server: SokEvo/1.0
  WWW-Authenticate: Basic realm=”google.com”
  Content-Type: text/html
  Content-Length: xxx

  3. 當(dāng)符合http1.0或1.1規(guī)范的客戶端(如IE,F(xiàn)IREFOX)收到401返回值時,將自動彈出一個登錄窗口,要求用戶輸入用戶名和密碼。

  4. 用戶輸入用戶名和密碼后,將用戶名及密碼以BASE64加密方式加密,并將密文放入前一條請求信息中,則客戶端發(fā)送的第一條請求信息則變成如下內(nèi)容:

  Get /index.html HTTP/1.0
  Host:www.google.com
  Authorization: Basic d2FuZzp3YW5n

注:d2FuZzp3YW5n表示加密后的用戶名及密碼(用戶名:密碼 然后通過base64加密,加密過程是瀏覽器默認(rèn)的行為,不需要我們?nèi)藶榧用?,我們只需要輸入用戶名密碼即可)

  5. 服務(wù)器收到上述請求信息后,將Authorization字段后的用戶信息取出、解密,將解密后的用戶名及密碼與用戶數(shù)據(jù)庫進(jìn)行比較驗證,如用戶名及密碼正確,服務(wù)器則根據(jù)請求,將所請求資源發(fā)送給客戶端

效果: 

客戶端未未認(rèn)證的時候,會彈出用戶名密碼輸入框,這個時候請求時屬于pending狀態(tài),這個時候其實服務(wù)當(dāng)用戶輸入用戶名密碼的時候客戶端會再次發(fā)送帶Authentication頭的請求。

web開發(fā)中前后端常見的鑒權(quán)方式有哪些

認(rèn)證成功:

web開發(fā)中前后端常見的鑒權(quán)方式有哪些

server.js

let express = require("express");
let app = express();

  app.use(express.static(__dirname+'/public'));

  app.get("/Authentication_base",function(req,res){
    console.log('req.headers.authorization:',req.headers)
    if(!req.headers.authorization){
      res.set({
        'WWW-Authenticate':'Basic realm="wang"'
      });
      res.status(401).end();
    }else{
      let base64 = req.headers.authorization.split(" ")[1];
      let userPass = new Buffer(base64, 'base64').toString().split(":");
      let user = userPass[0];
      let pass = userPass[1];
      if(user=="wang"&&pass="wang"){
        res.end("OK");
      }else{
        res.status(401).end();
      }

    }

  })

  app.listen(9090)

index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>HTTP Basic Authentication</title>
  </head>
  <body>
    <div></div>
    <script src="js/jquery-3.2.1.js"></script>
    <script>
      $(function(){
       send('./Authentication_base');
      })
      var send = function(url){
            $.ajax({ 
            url : url, 
            method : 'GET', 
          });
      }
    </script>
  </body>
</html>

  當(dāng)然有登陸就有注銷,我們會發(fā)現(xiàn)當(dāng)我們認(rèn)證成功后每次請求請求頭都會帶上Authentication及里面的內(nèi)容,那么如何做到讓這次登陸失效的?

  網(wǎng)上查了半天,目前最有效的方式就是在注銷操作的時候,專門在服務(wù)器設(shè)置一個專門的注銷賬號,當(dāng)接收到的Authentication信息為注銷用戶名密碼的時候糾就帶便注銷成功了,而客戶端在注銷操作的時候,手動的的去修改請求頭重的Authentication,將他設(shè)置未服務(wù)器默認(rèn)的注銷賬號和密碼。

  通過上面的簡單講解 其實我們已經(jīng)可以返現(xiàn)這種驗證方式的缺陷加密方式簡單,僅僅是base64加密,這種加密方式是可逆的。同時在每個請求的頭上都會附帶上用戶名和密碼信息,這樣在外網(wǎng)是很容易被嗅探器探測到的。

總結(jié):

  正式因為這樣,這種加密方式一般多被用在內(nèi)部安全性要求不高的的系統(tǒng)上,只是相對的多,總的來說現(xiàn)在使用這種鑒權(quán)比較少了。如果項目需要部署在公網(wǎng)上,這種方式不推薦,當(dāng)然你也可以和SSL來加密傳輸,這樣會好一點,這個如果我后面有時間來研究一下。

二.session-cookie

第二種這個方式是利用服務(wù)器端的session(會話)和瀏覽器端的cookie來實現(xiàn)前后端的認(rèn)證,由于http請求時是無狀態(tài)的,服務(wù)器正常情況下是不知道當(dāng)前請求之前有沒有來過,這個時候我們?nèi)绻涗洜顟B(tài),就需要在服務(wù)器端創(chuàng)建一個會話(seesion),將同一個客戶端的請求都維護(hù)在各自得會會話中,每當(dāng)請求到達(dá)服務(wù)器端的時候,先去查一下該客戶端有沒有在服務(wù)器端創(chuàng)建seesion,如果有則已經(jīng)認(rèn)證成功了,否則就沒有認(rèn)證。
session-cookie認(rèn)證主要分四步:
  1,服務(wù)器在接受客戶端首次訪問時在服務(wù)器端創(chuàng)建seesion,然后保存seesion(我們可以將seesion保存在內(nèi)存中,也可以保存在redis中,推薦使用后者),然后給這個session生成一個唯一的標(biāo)識字符串,然后在響應(yīng)頭中種下這個唯一標(biāo)識字符串。
   2.簽名。這一步只是對sid進(jìn)行加密處理,服務(wù)端會根據(jù)這個secret密鑰進(jìn)行解密。(非必需步驟)
  3.瀏覽器中收到請求響應(yīng)的時候會解析響應(yīng)頭,然后將sid保存在本地cookie中,瀏覽器在下次http請求de 請求頭中會帶上該域名下的cookie信息,
   4.服務(wù)器在接受客戶端請求時會去解析請求頭cookie中的sid,然后根據(jù)這個sid去找服務(wù)器端保存的該客戶端的session,然后判斷該請求是否合法。

web開發(fā)中前后端常見的鑒權(quán)方式有哪些

server.js(nodejs+express+seesion+redis)

var express = require('express');
var RedisStore = require('connect-redis')(express.session);
var app = express();
var secret = "wang839305939"
// 設(shè)置 Cookie
app.use(express.cookieParser(secret));

// 設(shè)置 Session
app.use(express.session({
 store: new RedisStore({
  host: "127.0.0.1",
  port: 6379,
  db: "session_db"
 }),
 secret: secret
}))

app.get("/", function(req, res) {
 var session = req.session;
 session.time= session.time|| 0;
 var n = session.time++;
 res.send('hello, session id:' + session.id + ' count:' + n);
});

app.listen(9080);

三.Token 驗證

使用基于 Token 的身份驗證方法,大概的流程是這樣的:

  1. 客戶端使用用戶名跟密碼請求登錄
  2. 服務(wù)端收到請求,去驗證用戶名與密碼
  3. 驗證成功后,服務(wù)端會簽發(fā)一個 Token,再把這個 Token 發(fā)送給客戶端
  4. 客戶端收到 Token 以后可以把它存儲起來,比如放在 Cookie 里或者 Local Storage 里
  5. 客戶端每次向服務(wù)端請求資源的時候需要帶著服務(wù)端簽發(fā)的 Token
  6. 服務(wù)端收到請求,然后去驗證客戶端請求里面帶著的 Token,如果驗證成功,就向客戶端返回請求的數(shù)據(jù)

  總的來說就是客戶端在首次登陸以后,服務(wù)端再次接收http請求的時候,就只認(rèn)token了,請求只要每次把token帶上就行了,服務(wù)器端會攔截所有的請求,然后校驗token的合法性,合法就放行,不合法就返回401(鑒權(quán)失敗)。

  乍的一看好像和前面的seesion-cookie有點像,seesion-cookie是通過seesionid來作為瀏覽器和服務(wù)端的鏈接橋梁,而token驗證方式貌似是token來起到seesionid的角色。其實這兩者差別是很大的。
  1. sessionid 他只是一個唯一標(biāo)識的字符串,服務(wù)端是根據(jù)這個字符串,來查詢在服務(wù)器端保持的seesion,這里面才保存著用戶的登陸狀態(tài)。但是token本身就是一種登陸成功憑證,他是在登陸成功后根據(jù)某種規(guī)則生成的一種信息憑證,他里面本身就保存著用戶的登陸狀態(tài)。服務(wù)器端只需要根據(jù)定義的規(guī)則校驗這個token是否合法就行。
  2. session-cookie是需要cookie配合的,居然要cookie,那么在http代理客戶端的選擇上就是只有瀏覽器了,因為只有瀏覽器才會去解析請求響應(yīng)頭里面的cookie,然后每次請求再默認(rèn)帶上該域名下的cookie。但是我們知道http代理客戶端不只有瀏覽器,還有原生APP等等,這個時候cookie是不起作用的,或者瀏覽器端是可以禁止cookie的(雖然可以,但是這基本上是屬于吃飽沒事干的人干的事)…,但是token 就不一樣,他是登陸請求在登陸成功后再請求響應(yīng)體中返回的信息,客戶端在收到響應(yīng)的時候,可以把他存在本地的cookie,storage,或者內(nèi)存中,然后再下一次請求的請求頭重帶上這個token就行了。簡單點來說cookie-session機制他限制了客戶端的類型,而token驗證機制豐富了客戶端類型。
   3. 時效性。session-cookie的sessionid實在登陸的時候生成的而且在登出事時一直不變的,在一定程度上安全就會低,而token是可以在一段時間內(nèi)動態(tài)改變的。
   4. 可擴展性。token驗證本身是比較靈活的,一是token的解決方案有許多,常用的是JWT,二來我們可以基于token驗證機制,專門做一個鑒權(quán)服務(wù),用它向多個服務(wù)的請求進(jìn)行統(tǒng)一鑒權(quán)。

下面就拿最常用的JWT(JSON WEB TOKEN)來說:

   JWT是Auth0提出的通過對JSON進(jìn)行加密簽名來實現(xiàn)授權(quán)驗證的方案,就是登陸成功后將相關(guān)信息組成json對象,然后對這個對象進(jìn)行某中方式的加密,返回給客戶端,客戶端在下次請求時帶上這個token,服務(wù)端再收到請求時校驗token合法性,其實也就是在校驗請求的合法性。
JWT對象通常由三部分構(gòu)成:

Headers: 包括類別(typ)、加密算法(alg)

 {
   "alg": "HS256",
   "typ": "JWT"
  }

Claims :包括需要傳遞的用戶信息

  {
   "sub": "1234567890",
   "name": "John Doe",
   "admin": true
  }

Signature: 根據(jù)alg算法與私有秘鑰進(jìn)行加密得到的簽名字串, 這一段是最重要的敏感信息,只能在服務(wù)端解密;

HMACSHA256( 
  base64UrlEncode(Headers) + "." +
  base64UrlEncode(Claims),
  SECREATE_KEY
)

編碼之后的JWT看起來是這樣的一串字符:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

nodejs+express+jwt-simple

auth.js

let jwt = require('jwt-simple');
let secret = "wangyy";
let time = 10;
 module.exports = { 
 /*
 *檢驗token合法性
 */ 
 validate:function(req,res,next){ 
   let token = req.body.token||req.headers["xssToken"];
    if(token){ 
     let decodeToken = null;
     try { //防止假冒token解析報錯 
       decodeToken = jwt.decode(token,secret,'HS256'); 
     } catch (err) { 
      res.status(401).send("非法訪問"); return; 
     } 
    let exp = decodeToken.exp; if(!exp){
    res.status(401).send("非法訪問");
   }
   let now = new Date().getTime();
   if(exp>(now+time*60*1000)){
    res.send({code:'002',"errorMsg":"授權(quán)超時"})
   }
   next();
  }else{ 
    res.status(401).send("非法訪問");
  }
 },
 /* 生成token*/ 
 makeToken(){ 
   let Token = null; 
   let payload = { 
       time:new Date().getTime(), 
       exp:this.makeExp(time) 
       } 
   Token = jwt.encode(payload,secret,HS256) return Token; 
 }, 
 /*生成token過期時間*/ 
 makeExp:function(time){
   let stam = time601000; 
  } 
 }

server.js

let express = require("express"); 
let app = express(); 
let bodyParser = require('body-parser'); 
let auth = require('./lib/auth.js'); 
let chalk = require('chalk'); app.use(bodyParser.json()); app.post('/login',function(req,res,next){ 
      let Token = auth.makeToken(); 
      res.json({result:"success",token:Token},200)
  });
app.use('*',[auth.validate],function(req,res,next){ 
   res.send('success'); 
 }); 
app.listen('9999')

  上面只是一個簡單的token生成和校驗,如果有需要可以根據(jù)實際需要進(jìn)行邏輯處理

四.OAuth(開放授權(quán))

  OAuth(開放授權(quán))是一個開放標(biāo)準(zhǔn),允許用戶授權(quán)第三方網(wǎng)站訪問他們存儲在另外的服務(wù)提供者上的信息,而不需要將用戶名和密碼提供給第三方網(wǎng)站或分享他們數(shù)據(jù)的所有內(nèi)容,為了保護(hù)用戶數(shù)據(jù)的安全和隱私,第三方網(wǎng)站訪問用戶數(shù)據(jù)前都需要顯式的向用戶征求授權(quán)。我們常見的提供OAuth認(rèn)證服務(wù)的廠商有支付寶,QQ,微信。
  OAuth協(xié)議又有1.0和2.0兩個版本。相比較1.0版,2.0版整個授權(quán)驗證流程更簡單更安全,也是目前最主要的用戶身份驗證和授權(quán)方式。

下面是一張auth3.0的流程圖:

web開發(fā)中前后端常見的鑒權(quán)方式有哪些

從圖中我們可以看出,auth3.0流程分為六布(我們就以csdn登陸為例):

第一步. 向用戶請求授權(quán),現(xiàn)在很多的網(wǎng)站在登陸的時候都有第三方登陸的入口,當(dāng)我們點擊等第三方入口時,第三方授權(quán)服務(wù)會引導(dǎo)我們進(jìn)入第三方登陸授權(quán)頁面。

web開發(fā)中前后端常見的鑒權(quán)方式有哪些

通過第三方請求授權(quán)頁面的瀏覽器地址欄地址可以看出,

https://graph.qq.com/oauth3.0/show?which=Login&display=pc&response_type=code&client_id=100270989&redirect_uri=https%3A%2F%2Fpassport.csdn.net%2Faccount%2Flogin%3Foauth_provider%3DQQProvider&state=test

這里的地址里面的%是瀏覽器強制編碼后的顯示我們可以使用decodeURIComponent進(jìn)行解碼,解碼后是這樣:

https://graph.qq.com/oauth3.0/show?which=Login&display=pc&response_type=code&client_id=100270989&redirect_uri=https://passport.csdn.net/account/login?oauth_provider=QQProvider&state=test

這個url地址我們可以看見Auth3.0常見的幾個參數(shù):
      response_type,返回類型
      client_id,第三方應(yīng)用id,由授權(quán)服務(wù)器(qq)在第三方應(yīng)用提交時頒發(fā)給第三方應(yīng)用。
      redirect_uri,登陸成功重定向頁面
      oauth_provider,第三方授權(quán)提供方
      state,由第三方應(yīng)用給出的隨機碼
第二步. 返回用戶憑證(code),并返回一個憑證(code),當(dāng)用戶點擊授權(quán)并登陸后,授權(quán)服務(wù)器將生成一個用戶憑證(code)。這個用戶憑證會附加在重定向的地址redirect_uri的后面

https://passport.csdn.net/account/login?code=9e3efa6cea739f9aaab2&state=XXX

第3步. 請求授權(quán)服務(wù)器授權(quán):

  經(jīng)過第二部獲取code后后面的工作就可以交給后臺去處理的,和用戶的交互就結(jié)束了。接下來我的需要獲取Access Token,我們需要用他來向授權(quán)服務(wù)器獲取用戶信息等資源。
  第三方應(yīng)用后臺通過第二步的憑證(code)向授權(quán)服務(wù)器請求Access Token,這時候需要以下幾個信息:

  • client_id 標(biāo)識第三方應(yīng)用的id,由授權(quán)服務(wù)器(Github)在第三方應(yīng)用提交時頒發(fā)給第三方應(yīng)用

  • client_secret 第三方應(yīng)用和授權(quán)服務(wù)器之間的安全憑證,由授權(quán)服務(wù)器(Github)在第三方應(yīng)用提交時頒發(fā)給第三方應(yīng)用

  • code 第一步中返回的用戶憑證redirect_uri 第一步生成用戶憑證后跳轉(zhuǎn)到第二步時的地址

  • state 由第三方應(yīng)用給出的隨機碼

第四步. 授權(quán)服務(wù)器同意授權(quán)后,返回一個資源訪問的憑證(Access Token)。

第五步. 第三方應(yīng)用通過第四步的憑證(Access Token)向資源服務(wù)器請求相關(guān)資源。

第六步. 資源服務(wù)器驗證憑證(Access Token)通過后,將第三方應(yīng)用請求的資源返回。

從用戶角度來說,第三方授權(quán)可以讓我們快速的登陸應(yīng)用,無需進(jìn)行繁瑣的注冊,同時不用記住各種賬號密碼。只需要記住自己常用的幾個賬號就ok了。
從產(chǎn)品經(jīng)理的角度來所,這種授權(quán)方式提高用戶的體驗滿意度。另一方面可以獲取更多的用戶。

以上是“web開發(fā)中前后端常見的鑒權(quán)方式有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI