最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2019年08月30日 09:05:15   作者:shortlife  
這篇文章主要介紹了vue+koa2實(shí)現(xiàn)session、token登陸狀態(tài)驗(yàn)證的示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

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

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

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

koa + session 登陸驗(yàn)證

1、首先要安裝 koa-sisson 包

npm install koa-session -S

koa-session 實(shí)際上是通過 cookie 來保存信息的。koa-session 在服務(wù)器上生成一個(gè)信息,通過加密后,以 cookie 的形式發(fā)送到用戶的瀏覽器,在用戶瀏覽器上可以看到是一個(gè)加密的 cookie 字段,然后在服務(wù)端路由中通過 ctx.session.xx 來獲取 xx 這個(gè)信息。而當(dāng)每次當(dāng)用戶發(fā)送請(qǐng)求時(shí)候,就可以獲取到這個(gè) cookie,koa-sesscion 會(huì)內(nèi)部會(huì)幫我們解密為最初的存儲(chǔ)的信息,于是我們可以通過判斷這個(gè) cookie 是存在來校驗(yàn)用戶是否已經(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 的過期時(shí)間 */
 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),這句代碼會(huì)在瀏覽器中生成一個(gè)以 "koa:sess" 為 Name 的 cookie
  ctx.session.userInfo = {username: '', userID: ''}
  ctx.body = {code: 1, message: '登陸成功'}
 } else {
  ctx.body = {code: 0, message: '賬號(hào)或密碼錯(cuò)誤'}
 }
 } catch(err) {
 throw new Error(err)
 }
})

// 前端
axios.post('/login', {username: '', password: ''}).then(res => {})

4、校驗(yàn)是否已登陸

router.get('/getSession', async (ctx) => {
 try {
 if (ctx.session.userInfo) {
  ctx.body = {code: 1, message: '已登陸'}
 } else {
  ctx.body = {code: 0, message: '未登陸'}
  // 跳轉(zhuǎn)到登錄頁
  // 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
 // 跳轉(zhuǎn)到登錄頁或網(wǎng)站首頁
 ctx.response.redirect('/')
 } catch(err) {
 throw new Error(err)
 }
})

// 前端
axios.post('/logout').then(res => {})

koa + token 登陸驗(yàn)證

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: '賬號(hào)或密碼錯(cuò)誤'}
 }
 } 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 存儲(chǔ) userInfo 和登陸狀態(tài)
 store.commit('SET_USERINFO', {userInfo: res.data.data.userInfo, status: true})
 }
})

4、校驗(yàn)是否已登陸

router.get('/getUserInfo', async (ctx) => {
 try {
 const token = ctx.get('Authorization') // 獲取請(qǐng)求 Header 中 Authorization 值
 let userInfo = {}
 if (token === '') {
  ctx.body = {code: 0, message: '未登陸'}
 } else {
  try {
  userInfo = jwt.verify(token.split(' ')[1], tokenConfig.privateKey) // 驗(yàn)證 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)
 }
})

要每次的請(qǐng)求中都帶上 token 信息,要給 axios 設(shè)置請(qǐng)求攔截

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

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

// 路由守衛(wèi), 在跳轉(zhuǎn)之前執(zhí)行
router.beforeEach((to, from, next) => {
 let token = localStorage.getItem('token')
 let requireAuth = to.meta.requireAuth // VueRouter 里配置頁面是否需要登陸進(jìn)入
 let root = to.meta.root // VueRouter 里配置頁面是否需要登陸且管理員權(quán)限進(jìn)入
 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 存儲(chǔ) 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、退出登陸

因?yàn)榉?wù)器端并沒有存儲(chǔ)用戶登陸相關(guān)信息,只與前端是否存在 token 或是否能驗(yàn)證通過有關(guān),所以退出登陸就將 token 清除即可

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

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue組件與復(fù)用詳解

    vue組件與復(fù)用詳解

    組件 (Component) 是 Vue.js 最強(qiáng)大的功能之一。組件可以擴(kuò)展 HTML 元素,封裝可重用的代碼。這篇文章主要介紹了vue組件與復(fù)用,需要的朋友可以參考下
    2018-04-04
  • vue3+ElementPlus封裝函數(shù)式彈窗組件詳解

    vue3+ElementPlus封裝函數(shù)式彈窗組件詳解

    這篇文章主要為大家詳細(xì)介紹了如何利用vue3和ElementPlus封裝函數(shù)式彈窗組件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-08-08
  • Vue自定義復(fù)制指令 v-copy功能的實(shí)現(xiàn)

    Vue自定義復(fù)制指令 v-copy功能的實(shí)現(xiàn)

    這篇文章主要介紹了Vue自定義復(fù)制指令 v-copy,使用自定義指令創(chuàng)建一個(gè)點(diǎn)擊復(fù)制文本功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-01-01
  • Vue3?源碼分析reactive?readonly實(shí)例

    Vue3?源碼分析reactive?readonly實(shí)例

    這篇文章主要為大家介紹了Vue3?源碼分析reactive?readonly實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • vue文件使用iconfont解析

    vue文件使用iconfont解析

    這篇文章主要介紹了vue文件使用iconfont解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vite配置優(yōu)雅的code?spliiting代碼分割詳解

    Vite配置優(yōu)雅的code?spliiting代碼分割詳解

    這篇文章主要為大家介紹了Vite配置優(yōu)雅的code?spliiting代碼分割詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • vue第三方庫中存在擴(kuò)展運(yùn)算符報(bào)錯(cuò)問題的解決方案

    vue第三方庫中存在擴(kuò)展運(yùn)算符報(bào)錯(cuò)問題的解決方案

    這篇文章主要介紹了vue第三方庫中存在擴(kuò)展運(yùn)算符報(bào)錯(cuò)問題,本文給大家分享解決方案,通過結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • 在Vue中延遲執(zhí)行某個(gè)函數(shù)的實(shí)現(xiàn)方式

    在Vue中延遲執(zhí)行某個(gè)函數(shù)的實(shí)現(xiàn)方式

    在Vue中延遲執(zhí)行某個(gè)函數(shù),你可以使用setTimeout()函數(shù)或者Vue提供的生命周期鉤子函數(shù),本文通過一些示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-12-12
  • vue-cli 打包后提交到線上出現(xiàn)

    vue-cli 打包后提交到線上出現(xiàn) "Uncaught SyntaxError:Unexpected token" 報(bào)

    這篇文章主要介紹了vue-cli 打包后提交到線上出現(xiàn) "Uncaught SyntaxError:Unexpected token" 報(bào)錯(cuò),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-11-11
  • 在Vue開發(fā)過程中解決和預(yù)防內(nèi)存泄漏問題的方法詳解

    在Vue開發(fā)過程中解決和預(yù)防內(nèi)存泄漏問題的方法詳解

    Vue作為一款流行的前端框架,已經(jīng)在許多項(xiàng)目中得到廣泛應(yīng)用,然而,隨著我們?cè)赩ue中構(gòu)建更大規(guī)模的應(yīng)用程序,我們可能會(huì)遇到一個(gè)嚴(yán)重的問題,那就是內(nèi)存泄漏,因此,我們需要認(rèn)識(shí)到在Vue開發(fā)過程中,內(nèi)存泄漏問題的重要性,本文將給大家介紹如何解決和預(yù)防內(nèi)存泄漏問題
    2023-10-10

最新評(píng)論

宁南县| 星座| 东台市| 正宁县| 泗洪县| 亚东县| 米林县| 大关县| 九龙县| 西贡区| 肃宁县| 塘沽区| 元氏县| 乐业县| 信阳市| 巴彦县| 阳泉市| 白河县| 怀柔区| 鄂伦春自治旗| 永顺县| 宝山区| 青海省| 天等县| 商都县| 贡嘎县| 陆丰市| 五河县| 息烽县| 泊头市| 罗山县| 子洲县| 汝阳县| 独山县| 来凤县| 陇西县| 微博| 乳山市| 曲水县| 岢岚县| 逊克县|