<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
認證授權在業界已經有很多成熟的方案,但對於前端開發來說,大部分情況都是呼叫伺服器端提供登入介面完成認證,後續請求帶上對於 token 即可。相信不少公司還會開發 JS SDK,讓各個業務專案都能快速接入認證授權,所以認證授權的細節流程我們可能並沒有關注過。
本文將從前端視角介紹常見的認證授權方案,同時提供簡單的實踐來體驗流程。
認證 (Identification) 是驗證當前使用者的身份。
常見的認證技術:
授權 (Authorization) 指賦予使用者系統的存取許可權。認證完使用者身份後,系統會授予使用者部分或者全部許可權。系統要是沒有許可權控制需求的話,一般認證後用戶就有全部許可權。
實現授權的方式有:
鑑權 (Authentication) 是指系統鑑定使用者身份和許可權。比如系統需要鑑定 session/cookie/token 的合法性和有效性。
這三個概念的關係也是很清晰,就是一個前後依次發生的關係:認證 => 授權 => 鑑權。比如我們登入某個系統就完成了認證和授權,後續使用功能時就需要系統鑑權。
瞭解相關概念後,就可以開始介紹常見的認證授權方案。
基本認證 (Basic 認證) 是 HTTP/1.0 就定義的認證方式,主要通過使用者提供使用者名稱和密碼的方式,實現對使用者身份的驗證。
基本認證流程圖
認證步驟解析
node 的簡單實現
const express = require('express') const app = express() const protectedPath = '/protected_docs' const realms = { [protectedPath]: { users: ['root'], }, } app.get(protectedPath, (req, res, next) => { const realm = realms[req.path] const authorization = req.get('authorization') if (!authorization) { // 告知使用者需要身份認證 res.statusCode = 401 res.set('WWW-Authenticate', 'Basic realm=' + encodeURIComponent(realm)) res.end() return } const usernamePasswd = authorization.split(' ')[1] // Basic Y2h5aW5ncDoxMjM0NTY const [usrname, passwd] = Buffer.from(usernamePasswd, 'base64') .toString() .split(':') if (!realm.users.includes(usrname)) { // 使用者不在realm裡 res.statusCode = 401 res.set('WWW-Authenticate', 'Basic realm=' + encodeURIComponent(realm)) res.end() return } const isValid = usrname === 'root' && passwd === '123456' if (!isValid) { // 使用者賬號、密碼驗證不通過 res.statusCode = 403 res.end() return } res.end(`welecom ${usrname}`) }) app.listen(3000)
小結
優點:
缺點:
使用場景:
這邊提一下,HTTP1.1 針對基本認證缺點,提供了摘要認證(Digest 認證),原理簡單來說就是伺服器端會給瀏覽器一個 nonce 亂數,瀏覽器會將賬號、密碼和 nonce 等引數進行 md5 加密後傳給伺服器端(同時傳賬號資料,密碼不傳),伺服器端獲取到賬號後,從資料庫拿密碼同樣進行 md5 加密,加密後值和瀏覽器傳的一樣就認為認證成功。
摘要認證不再明文傳輸密碼、可以防重放和避免報文被篡改,但是需要和 Https 配合使用。
Session-Cookie 認證是利用伺服器端的 Session(對談)和瀏覽器(使用者端)的 Cookie 來實現的前後端通訊認證模式。
什麼是 Cookie
HTTP 是無狀態協定,伺服器端在接收到使用者端首次請求後,設定對應的 Cookie,隨後瀏覽器在請求帶上 Cookie,伺服器端就可以知道當前使用者端狀態。
Cookie 的特點:
什麼是 Session
Session 的抽象概念是對談,是無狀態協定通訊過程中,為了實現中斷/繼續操作,將使用者和伺服器之間的互動進行的一種抽象。
Session 一般流程是:伺服器端接收到使用者端首次請求後,設定一個 Session 來跟蹤使用者的對談,同時會給使用者端一個 Session ID,後續使用者端請求時在帶上 Session ID,伺服器端即可找到對應的 Session,此時雙方通訊就是有狀態的。
Session 特點:
Session-Cookie 流程
Session 流程中一般會設定 Session ID,通常 Session ID 會儲存在 瀏覽器 Cookie 中,接下來看下整體流程。
認證步驟解析
簡單程式碼範例
const express = require("express"); const app = express(); const bodyParser = require("body-parser"); const port = 3000; const session = require("express-session"); app.use(bodyParser()); app.use( session({ key: 'SESSION_ID', secret: "your_secret_key", resave: false, saveUninitialized: false, cookie: { maxAge: 1000 * 60 * 60 * 8, signed: true }, }) ); app.get("/", async function (req, res) { res.send(req.session); }); app.get("/login", async function (req, res) { const authInfo = { id: '1', username: 'user', } const isValid = true if (isValid) { req.session.authInfo = authInfo res.send({ success: true, info: "登入成功", }); } else { res.send({ success: false, info: "登入失敗", }); } }); app.listen(port, () => { console.log(`node listening at http://localhost:${port}`); });
使用 node 起好伺服器後,先存取 /login
,在存取首頁 /
, 可以看到首頁輸出使用者名稱。同時開啟 F12,在 Cookie 中可以看到 SESSION_ID 的資料。
小結
優點:
缺點:
使用場景:
上述介紹中,我們知道了 Session-Cookie 的一些缺點,及 Session 的維護給伺服器端造成很大困擾,必須找地方存放它,又要考慮分散式的問題,所以 Token 方案就出來了。
Token 是一個令牌,使用者端存取伺服器時,驗證通過後伺服器端會為其簽發一張令牌,之後,使用者端就可以攜帶令牌存取伺服器,伺服器端只需要驗證令牌的有效性即可。
一般 Token 的組成:
uid(使用者唯一的身份標識) + time(當前時間的時間戳) + sign(簽名,Token 的前幾位以雜湊演演算法壓縮成的一定長度的十六進位制字串)
Token 認證流程
認證步驟解析
Token的優缺點
優點:
缺點:
業務介面用來鑑權的 Token,我們稱之為 Access Token,為了安全性,Access Token 有效期一般設定的比較短。Access Token 過期後,需要使用者重新登入,但是這種體驗較差。
所以有了 Refresh Token, 可以用 Refresh Token 去獲取 Access Token。
Access Token:用來存取業務介面,由於有效期足夠短,盜用風險小。
Refresh Token:用來獲取 Access Token,有效期可以長一些,通過獨立服務和嚴格的請求方式增加安全性。
Refresh Token 的使用流程是在伺服器校驗 Token, 發現過期後,使用者端可以使用 Refresh Token 發起請求,獲取新的 Access Token 和 Refresh Token。
上述 Token 中,一般只有 uid 資訊,需要更多登入資訊和其他資料的話,這時就需要查詢資料庫。每次都需要查詢資料庫,就會帶來一些效能消耗。所以業界常用的 JWT 方案就出來了。
JWT 是 Auth0 提出的通過對 JSON 進行加密簽名來實現授權驗證的方案, 它的特點是自包含的,使用者資訊和認證是在一起的,無需像 Cookie-Session 一樣需要 Session 伺服器,或者像 Token 一樣存取資料庫獲取使用者資訊。
JWT 本質上就是一組字串,通過(.)切分成三個為 Base64 編碼的部分:
JWT 通常是這樣的:xxxxx.yyyyy.zzzzz。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 .eyJuYW1lIjoieGlhb21pbmciLCJkYXRhIjoiPT09PT09PT09PT09PSIsImlhdCI6MTY3OTgwNDA1NywiZXhwIjoxNjc5ODA0MTE3fQ .FdJ6UD4Ff5zOz83f4hRDh1C86kN5f8aO_KeEtIwt3cM
JWT 認證流程
其實 JWT 的認證流程與 Token 的認證流程差不多,只是不需要再單獨去查詢資料庫查詢使用者資訊。
JWT 範例
const { expressjwt: jwt } = require('express-jwt') const express = require('express') const app = express() const jsonwebtoken = require('jsonwebtoken') const secretOrPrivateKey = 'hello' //加密token 校驗token時要使用 app.use( jwt({ secret: secretOrPrivateKey, algorithms: ['HS256'], }).unless({ path: ['/getToken'], //除了這個地址,其他的URL都需要驗證 }) ) app.use(function (err, req, res, next) { if (err.name === 'UnauthorizedError') { res.status(401).send('invalid token...') } }) app.get('/getToken', function (req, res) { res.json({ result: 'ok', token: jsonwebtoken.sign( { name: 'xiaoming', data: '=============', }, secretOrPrivateKey, { expiresIn: 60 * 1, } ), }) }) app.get('/getData', function (req, res) { res.send('data') }) app.listen(3000)
服務啟動後,存取 /getToken
獲取 JWT,然後在 Postman 中請求 /getData
, Header 部分加上 Authorization: Bearer your jwt
,比如 Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoieGlhb21pbmciLCJkYXRhIjoiPT09PT09PT09PT09PSIsImlhdCI6MTY3OTgwNjkyOCwiZXhwIjoxNjc5ODA2OTg4fQ.qFOT9IS_T1ZNsWWheRXP9MxYPh1l3SBGWLtp8ocnKAE
。
JWT 的優缺點
優點:
缺點:
使用場景:
OAuth 這種方式登入相信大家都使用過,比如我們想登入某個網站時,通常會發現可以通過第三方的 QQ 或者微信登入,這個就是使用到了 OAuth。
OAuth 是一個開放標準,允許使用者授權第三方網站存取他們儲存在另外的服務提供者上的資訊,而不需要將使用者名稱和密碼提供給第三方網站。常見的提供 OAuth 認證服務的廠商:支付寶、QQ、微信、微博
OAuth 認證流程
認證步驟解析
client_id
直接重定向到授權伺服器登入頁面,授權伺服器要求使用者端登入。code
,伺服器攜帶 client_id
, client_secret
, code
向授權伺服器請求令牌。使用 github 登入範例
準備工作:
1、建立 OAuth App
2、填寫基本資訊
3、獲取 client_id
和 client_secret
程式碼範例
const express = require('express') const app = express() const querystring = require('querystring') const axios = require('axios') // GitHub登入引數設定;設定授權應用生成的Client ID和Client Secret const config = { client_id: 'xxx', client_secret: 'xxxxxx' } // 登入介面 app.get('/github/login', function (req, res) { // 重定向到GitHub認證介面,並設定引數 let path = 'https://github.com/login/oauth/authorize?client_id=' + config.client_id // 轉發到授權伺服器 res.redirect(path) }) // GitHub授權登入成功回撥,地址必須與GitHub設定的回撥地址一致 app.get('/passport/github/callback', async function (req, res) { console.log('callback...') // 伺服器認證成功,回撥帶回認證狀態code const code = req.query.code const params = { client_id: config.client_id, client_secret: config.client_secret, code: code } // 申請令牌token let tokenRes = await axios.post('https://github.com/login/oauth/access_token', params) const access_token = querystring.parse(tokenRes.data).access_token // 根據token獲取使用者資訊 userRes = await axios.get(`https://api.github.com/user`, { headers: { 'Authorization': 'token ' + access_token } }) // 渲染頁面 res.end(` <h1>Hello ${userRes.data.login}</h1> <img src="${userRes.data.avatar_url}" alt=""> `) }) app.listen(7001, () => { console.log('listening port at 7001...') })
服務啟動後,存取 /github/login
,後續會跳轉 github 登入授權,完成後即可看到你的 github 使用者名稱和頭像。
登入的認證授權方式有很多,上述講到的都是一些常見的方案,當前方案的具體細節實施各個專案方還是會有差異的。
除了上述的內容後,認證授權這塊還有單點登入(SSO)、掃描登入、手機號一鍵登入等等方式,後續有機會在講。
以上就是JS前端認證授權技巧歸納總結的詳細內容,更多關於JS前端認證授權的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45