前端项目中的鉴权是如何实现的?

一、token 验证登录流程

使用基于 Token 的身份验证方法,大概的流程是这样的:

  1. 客户端使用用户名跟密码请求登录
  2. 服务端收到请求,去验证用户名与密码
  3. 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
  4. 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
  5. 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
  6. 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

总的来说就是客户端在首次登陆以后,服务端再次接收http请求的时候,就只认token了,请求只要每次把token带上就行了,服务器端会拦截所有的请求,然后校验token的合法性,合法就放行,不合法就返回401(鉴权失败)。


二、最常用的鉴权是 JWT方案(JSON WEB TOKEN)

JWT是什么?

JWT是Auth0提出的通过对JSON进行加密签名来实现授权验证的方案。就是登陆成功后将相关信息组成json对象,然后对这个对象进行某中方式的加密,返回给客户端,客户端在下次请求时带上这个token,服务端再收到请求时校验token合法性,其实也就是在校验请求的合法性。
JWT对象通常由三部分构成:

Headers: 包括类别(typ)、加密算法(alg)


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

Claims :包括需要传递的用户信息

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

Signature: 根据alg算法与私有秘钥进行加密得到的签名字串, 这一段是最重要的敏感信息,只能在服务端解密;

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.Authorization||req.headers["Authorization"];
        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:'401',"errorMsg":"授权超时"})
      }
      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生成和校验,如果有需要可以根据实际需要进行逻辑处理

四、前端设计

使用vuex保存全局状态,并做数据持久化
vuex里面面定义token变量来表示用户是否登录,初始值为’’


import createPersistedState from 'vuex-persistedstate'

export default new Vuex.Store({
	  state: {
	    token: '',
	  },
	  mutations: {
	    setIsLogin(state, isLogin) {  //登录成功调用
	      state.token = isLogin;
	    },
	    FedLogOut(state) {        //退出登陆执行
	      state.token=''
	    }
	  }
    actions,
    getters,
    plugins:[createPersistedState({  //vuex数据固化到本地缓存,数据持久化
        storage: window.localStorage
    })] 
});

配置request请求拦截器

request请求拦截器:发送请求前统一处理,如:设置请求头headers、应用的版本号、终端类型等。


service.interceptors.request.use(
  config => {
    if (store.state.token) {
     // 为请求头对象,添加token验证的Authorization字段
     config.headers.Authorization = store.state.token;     
    }
        return config
  },
  error => {
    // do something with request error
    console.log(error) // for debug
    return Promise.reject(error)
  }
)

response响应拦截器

response响应拦截器:有时候我们要根据响应的状态码来进行下一步操作,例如:由于当前的token过期,接口返回401未授权,那我们就要进行重新登录的操作。


service.interceptors.response.use(
  response => {
    Toast.clear()
    const res = response.data
    if (res.status && res.status !== 200) {
      // 登录超时,token过期返回401,重新登录
      if (res.status === 401) { 
        store.dispatch('FedLogOut').then(() => {
                router.replace({
                path: '/login'
                //登录成功后跳入浏览的当前页面
                // query: {redirect: router.currentRoute.fullPath}
            })
        })
      }
      return Promise.reject(res || 'error')
    } else {
      return Promise.resolve(res)
    }
  },
  error => {
    Toast.clear()
    console.log('err' + error) // for debug
    return Promise.reject(error)
  }
)

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现用户登录角色鉴权可以分为以下几个步骤: 1. 创建路由配置文件 在路由配置文件定义不同的路由,每个路由对应一种权限。例如,管理员可以访问所有的路由,而普通用户只能访问部分路由。 ``` import Vue from 'vue' import Router from 'vue-router' import Admin from '@/views/Admin' import User from '@/views/User' import Login from '@/views/Login' Vue.use(Router) export default new Router({ routes: [ { path: '/admin', name: 'Admin', component: Admin, meta: { requiresAuth: true, roles: ['admin'] } }, { path: '/user', name: 'User', component: User, meta: { requiresAuth: true, roles: ['admin', 'user'] } }, { path: '/', name: 'Login', component: Login } ] }) ``` 2. 创建登录页 在登录页,用户输入用户名和密码后,将其发送至后端进行验证。验证通过后,后端返回一个包含用户信息和token的响应结果。前端可以将token存储在localStorage或sessionStorage,以便在后续的请求携带token。 3. 创建路由守卫 路由守卫可以用来检测用户是否有权限访问某个路由。在路由守卫,可以检查localStorage或sessionStorage是否存在token。如果不存在,则跳转到登录页;如果存在,则从token解析出用户信息,并检查用户是否有权限访问该路由。如果有权限,则继续访问该路由;如果没有权限,则跳转到没有权限的提示页面。 ``` import router from './router' // 路由守卫 router.beforeEach((to, from, next) => { // 判断该路由是否需要登录权限 if (to.meta.requiresAuth) { // 从localStorage获取token const token = window.localStorage.getItem('token') if (token) { // 解析token,获取用户信息 const payload = JSON.parse(atob(token.split('.')[1])) // 检查用户是否有权限访问该路由 if (to.meta.roles.includes(payload.role)) { next() } else { next('/unauthorized') } } else { next('/login') } } else { next() } }) ``` 4. 根据用户角色展示不同的菜单 在应用的导航栏或侧边栏,根据用户角色动态地展示不同的菜单。可以通过computed属性计算出当前用户有权限访问的菜单,并将其渲染到视图。 ``` <template> <div> <ul> <li v-if="showAdminMenu"><router-link to="/admin">管理页面</router-link></li> <li v-if="showUserMenu"><router-link to="/user">用户页面</router-link></li> </ul> </div> </template> <script> export default { computed: { showAdminMenu() { const token = window.localStorage.getItem('token') if (token) { const payload = JSON.parse(atob(token.split('.')[1])) return payload.role === 'admin' } else { return false } }, showUserMenu() { const token = window.localStorage.getItem('token') if (token) { const payload = JSON.parse(atob(token.split('.')[1])) return ['admin', 'user'].includes(payload.role) } else { return false } } } } </script> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值