認證登陸就是經過第三方受權來鑑別用戶信息的登陸方式,好比:微信掃碼登陸。目前最爲普遍接受的受權標準是 OAuth2.0,基於 OAuth2.0 的認證登陸本質上是 Web 應用在用戶受權下獲取該用戶在第三方應用上的我的信息的過程:html
OAuth2.0 定義了框架但具體實現根據廠商不一樣多少存在差別,而 passport 模塊提供了抹平這種差別的機制,經過接入不一樣的 strategy
對象能夠對接不一樣的第三方登陸。本章將基於上一章已完成的工程 host1-tech/nodejs-server-examples - 06-session 接入 passport 模塊實現 Github 認證登陸。先在工程根目錄安裝 passport 與 passport-github:node
$ yarn add passport # 本地安裝 passport # ... info Direct dependencies └─ passport@0.4.1 # ... $ yarn add passport-github # 本地安裝 passport-github # ... info Direct dependencies └─ passport-github@1.1.0 # ...
接下來在 Github 上新建 OAuth 應用:git
而後加上 Github 登陸方式:github
// src/middlewares/auth.js const passport = require('passport'); const { Strategy: GithubStrategy } = require('passport-github'); const GITHUB_STRATEGY_OPTIONS = { clientID: 'b8ada004c6d682426cfb', clientSecret: '0b13f2ab5651f33f879a535fc2b316c6c731a041', callbackURL: 'http://localhost:9000/api/login/github/callback', }; const githubStrategy = new GithubStrategy( GITHUB_STRATEGY_OPTIONS, (accessToken, refreshToken, profile, done) => { /** * 根據 profile 查找或新建 user 信息 */ const user = {}; done(null, user); } ); passport.use(githubStrategy); passport.serializeUser((user, done) => { /** * 根據 user 信息獲取 userId */ const userId = '46e5'; done(null, userId); }); passport.deserializeUser((userId, done) => { /** * 根據 userId 獲取 user 信息 */ const user = {}; done(null, user); }); module.exports = function authMiddleware() { return [passport.initialize(), passport.session()]; }; Object.assign(module.exports, { passport });
// src/middlewares/index.js const { Router } = require('express'); const cookieParser = require('cookie-parser'); const sessionMiddleware = require('./session'); const urlnormalizeMiddleware = require('./urlnormalize'); const loginMiddleware = require('./login'); +const authMiddleware = require('./auth'); const secret = '842d918ced1888c65a650f993077c3d36b8f114d'; module.exports = async function initMiddlewares() { const router = Router(); router.use(urlnormalizeMiddleware()); router.use(cookieParser(secret)); router.use(sessionMiddleware(secret)); router.use(loginMiddleware()); + router.use(authMiddleware()); return router; };
// src/middlewares/login.js const { parse } = require('url'); module.exports = function loginMiddleware( homepagePath = '/', loginPath = '/login.html', whiteList = { '/500.html': ['get'], '/api/health': ['get'], '/api/login': ['post'], + '/api/login/github': ['get'], + '/api/login/github/callback': ['get'], } ) { //... };
// src/controllers/login.js const { Router } = require('express'); +const { passport } = require('../middlewares/auth'); class LoginController { + homepagePath; + loginPath; + async init() { const router = Router(); router.post('/', this.post); + router.get( + '/github', + passport.authenticate('github', { scope: ['read:user'] }) + ); + router.get( + '/github/callback', + passport.authenticate('github', { + failureRedirect: this.loginPath, + }), + this.getGithubCallback + ); return router; } post = (req, res) => { req.session.logined = true; - res.redirect('/'); + res.redirect(this.homepagePath); }; + + getGithubCallback = (req, res) => { + req.session.logined = true; + res.redirect(this.homepagePath); + }; } -module.exports = async () => { +module.exports = async (homepagePath = '/', loginPath = '/login.html') => { const c = new LoginController(); + Object.assign(c, { homepagePath, loginPath }); return await c.init(); };
<!-- public/login.html --> <html> <head> <meta charset="utf-8" /> </head> <body> <form method="post" action="/api/login"> <button type="submit">一鍵登陸</button> </form> + <a href="/api/login/github"><button>Github 登陸</button></a> </body> </html>
訪問 http://localhost:9000/login.html 便可體驗 Github 認證登陸邏輯:數據庫
須要注意因爲 Github 服務器在海外,偶爾會出現網絡不通致使的認證異常,此時只要稍等一段時間再試就能夠了。另外,登陸過的讀者能夠經過清除 Cookie 重置登陸狀態。express
host1-tech/nodejs-server-examples - 07-authenticationsegmentfault
從零搭建 Node.js 企業級 Web 服務器(零):靜態服務
從零搭建 Node.js 企業級 Web 服務器(一):接口與分層
從零搭建 Node.js 企業級 Web 服務器(二):校驗
從零搭建 Node.js 企業級 Web 服務器(三):中間件
從零搭建 Node.js 企業級 Web 服務器(四):異常處理
從零搭建 Node.js 企業級 Web 服務器(五):數據庫訪問
從零搭建 Node.js 企業級 Web 服務器(六):會話
從零搭建 Node.js 企業級 Web 服務器(七):認證登陸
從零搭建 Node.js 企業級 Web 服務器(八):網絡安全api