国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

vue+koa2實現(xiàn)session、token登陸狀態(tài)驗證的示例

2019-11-19 10:56:21
字體:
來源:轉載
供稿:網(wǎng)友

Session 登陸與 Token 登陸的區(qū)別

1、Session 登陸是在服務器端生成用戶相關 session 數(shù)據(jù),發(fā)給客戶端 session_id 存放到 cookie 中,這樣在客戶端請求時帶上 session_id 就可以驗證服務器端是否存在 session 數(shù)據(jù),以此完成用戶認證。這種認證方式,可以更好的在服務端對會話進行控制,安全性比較高(session_id 隨機),但是服務端需要存儲 session 數(shù)據(jù)(如內存或數(shù)據(jù)庫),這樣無疑增加維護成本和減弱可擴展性(多臺服務器)。 CSRF 攻擊一般基于 cookie。另外,如果是原生 app 使用這種服務接口,因為沒有瀏覽器 cookie 功能,所以接入會相對麻煩。

2、基于 token 的用戶認證是一種服務端無狀態(tài)的認證方式,服務端不用存放 token 數(shù)據(jù)。用戶驗證后,服務端生成一個 token(hash 或 encrypt)發(fā)給客戶端,客戶端可以放到 cookie 或 localStorage 中,每次請求時在 Header 中帶上 token,服務端收到 token,通過驗證后即可確認用戶身份。這種方式相對 cookie 的認證方式就簡單一些,服務端不用存儲認證數(shù)據(jù),易維護擴展性強,token 存在 localStorage 可避免 CSRF,web 和 app 應用都比較簡單。不過這種方式在加密或解密的時候會有一些性能開銷(好像也不是很大),有些對稱加密存在安全隱患(aes cbc 字節(jié)翻轉攻擊)。

koa + session 登陸驗證

1、首先要安裝 koa-sisson 包

npm install koa-session -S

koa-session 實際上是通過 cookie 來保存信息的。koa-session 在服務器上生成一個信息,通過加密后,以 cookie 的形式發(fā)送到用戶的瀏覽器,在用戶瀏覽器上可以看到是一個加密的 cookie 字段,然后在服務端路由中通過 ctx.session.xx 來獲取 xx 這個信息。而當每次當用戶發(fā)送請求時候,就可以獲取到這個 cookie,koa-sesscion 會內部會幫我們解密為最初的存儲的信息,于是我們可以通過判斷這個 cookie 是存在來校驗用戶是否已經(jīng)登錄了。

2、app.js 中初始化

const Koa = require('koa')const app = new Koa()const session = require('koa-session')const bodyParser = require('koa-bodyparser')const Router = require('koa-router')const router = new Router()const CONFIG = { key: 'koa:sess', /** (string) cookie key (default is koa:sess) cookie 的Name */ /** (number || 'session') maxAge in ms (default is 1 days) */ /** 'session' will result in a cookie that expires when session/browser is closed */ /** Warning: If a session cookie is stolen, this cookie will never expire */ maxAge: 86400000, /** cookie 的過期時間 */ autoCommit: true, /** (boolean) automatically commit headers (default true) */ overwrite: true, /** (boolean) can overwrite or not (default true) */ httpOnly: true, /** (boolean) httpOnly or not (default true) */ signed: true, /** (boolean) signed or not (default true) */ rolling: false, /** (boolean) Force a session identifier cookie to be set on every response. The expiration is reset to the original maxAge, resetting the expiration countdown. (default is false) */ renew: false, /** (boolean) renew session when session is nearly expired, so we can always keep user logged in. (default is false)*/}app.keys = ['login secret'] // 加密密鑰app.use(session(CONFIG, app));app.use(bodyParser())app.use(router.routes()).use(router.allowedMethods())

3、登陸路由

router.post('/login', async (ctx) => { try { const data = ctx.request.body.data const { username, password } = data if (true) {  // 保存登錄狀態(tài),這句代碼會在瀏覽器中生成一個以 "koa:sess" 為 Name 的 cookie  ctx.session.userInfo = {username: '', userID: ''}  ctx.body = {code: 1, message: '登陸成功'} } else {  ctx.body = {code: 0, message: '賬號或密碼錯誤'} } } catch(err) { throw new Error(err) }})// 前端axios.post('/login', {username: '', password: ''}).then(res => {})

4、校驗是否已登陸

router.get('/getSession', async (ctx) => { try { if (ctx.session.userInfo) {  ctx.body = {code: 1, message: '已登陸'} } else {  ctx.body = {code: 0, message: '未登陸'}  // 跳轉到登錄頁  // ctx.response.redirect('/login')  } } catch(err) { throw new Error(err) }})// 前端axios.get('/getSession').then(res => {})

5、退出登陸

router.post('/logout', async (ctx) => { try { // 將登錄信息清空 ctx.session = null // 跳轉到登錄頁或網(wǎng)站首頁 ctx.response.redirect('/') } catch(err) { throw new Error(err) }})// 前端axios.post('/logout').then(res => {})

koa + token 登陸驗證

1、安裝 jsonwebtoken 包

npm install jsonwebtoken -S

2、app.js 初始化

const Koa = require('koa')const app = new Koa()const jwt = require('jsonwebtoken')const bodyParser = require('koa-bodyparser')const Router = require('koa-router')const router = new Router()const tokenConfig = {privateKey: 'xxxxxxxxxxxx'} // 加密密鑰app.use(bodyParser())app.use(router.routes()).use(router.allowedMethods())

3、登陸路由

router.post('/login', async (ctx) => { try { const data = ctx.request.body.data const { username, password } = data if (true) {  const userInfo = {username: '', userID: ''}  const token = jwt.sign(userInfo, tokenConfig.privateKey, {expiresIn: '7d'}) // 簽發(fā) token, 7天有效期  ctx.body = {code: 1, message: '登陸成功', data: {token: 'Bearer ' + token}} } else {  ctx.body = {code: 0, message: '賬號或密碼錯誤'} } } catch(err) { throw new Error(err) }})

前端登陸

axios.post('/login', {username: '', password: ''}).then(res => { if (res.data.code === 1) { localStorage.setItem('token', res.data.data.token) // vuex 存儲 userInfo 和登陸狀態(tài) store.commit('SET_USERINFO', {userInfo: res.data.data.userInfo, status: true}) }})

4、校驗是否已登陸

router.get('/getUserInfo', async (ctx) => { try { const token = ctx.get('Authorization') // 獲取請求 Header 中 Authorization 值 let userInfo = {} if (token === '') {  ctx.body = {code: 0, message: '未登陸'} } else {  try {  userInfo = jwt.verify(token.split(' ')[1], tokenConfig.privateKey) // 驗證 token  ctx.body = {code: 1, message: '已登陸', data: {userInfo: userInfo: loginStatus: true}}  } catch(err) {  // token 過期或無效  ctx.body = {code: 0, message: '未登陸', data: {userInfo: {}: loginStatus: false}}}  } } } catch(err) { throw new Error(err) }})

要每次的請求中都帶上 token 信息,要給 axios 設置請求攔截

// 請求攔截,在每次請求中的 header 中帶上 tokenaxios.interceptors.request.use(config => { let token = localStorage.getItem('token') if (token) { config.headers.common.Authorization = token } return config}, error => { return Promise.reject(error);})

每次進入頁面之前要判斷下是否已登陸,是否有權限進入該頁面,之前我是在每個頁面的 created 鉤子函數(shù)中去請求 '/getUserInfo' 判斷是否以登陸,這樣做繁瑣,并且頁面會先呈現(xiàn)一下,然后一閃而過(驗證不過的情況下),在路由鉤子函數(shù)中可全局配置

// 路由守衛(wèi), 在跳轉之前執(zhí)行router.beforeEach((to, from, next) => { let token = localStorage.getItem('token') let requireAuth = to.meta.requireAuth // VueRouter 里配置頁面是否需要登陸進入 let root = to.meta.root // VueRouter 里配置頁面是否需要登陸且管理員權限進入 if (!token) { // vuex 清除 userInfo 和登陸狀態(tài) store.commit('SET_USERINFO', {userInfo: {}, status: false}) requireAuth ? next({path: '/'}) : next() } else { axios.get(API.getUserInfo).then(res => {  // vuex 存儲 userInfo 和登陸狀態(tài)  store.commit('SET_USERINFO', {userInfo: res.data.userInfo, status: res.data.loginStatus})  if (requireAuth) {  if (!res.data.loginStatus || (root && !res.data.userInfo.root)) {   next({path: '/'})  } else {   next()  }  } else {  next()  } }) }})/** VueRouter{ path: '/admin', name: 'admin', meta: { requireAuth: true, root: true },}*/

5、退出登陸

因為服務器端并沒有存儲用戶登陸相關信息,只與前端是否存在 token 或是否能驗證通過有關,所以退出登陸就將 token 清除即可

methods: { logout() { localStorage.removeItem('token') // vuex 清除登陸信息 store.commit('SET_USERINFO', {userInfo: {}, status: false}) if (this.$route.path !== '/') {  this.$router.push({path: '/'}) } }}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 济阳县| 留坝县| 双鸭山市| 呼和浩特市| 湘潭市| 和平县| 太仆寺旗| 邛崃市| 景谷| 宣武区| 开封县| 许昌市| 弋阳县| 滕州市| 湘潭市| 涞水县| 平凉市| 吉隆县| 广饶县| 改则县| 兴义市| 东城区| 南靖县| 松潘县| 彰化县| 怀远县| 新乡市| 溆浦县| 蒲城县| 平陆县| 蒙城县| 山东省| 房产| 杭州市| 那坡县| 宁乡县| 宜春市| 武宁县| 屏南县| 青田县| 平江县|