IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 前后端分离登录 -> 正文阅读

[网络协议]前后端分离登录

1.http无协议

因为HTTP是无状态的协议,也就是说,这个协议是无法记录用户访问状态的,其每次请求都是独立的无关联的,一笔是一笔。而我们的网站都是设计成多个页面的,所在页面跳转过程中我们需要知道用户的状态,尤其是用户登录的状态,这样我们在页面跳转后我们才知道是否可以让用户有权限来操作一些功能或是查看一些数据。

所以,我们每个页面都需要对用户的身份进行认证。为了实现这一功能,用得最多的技术就是浏览器的cookie,我们会把用户登录的信息存放在客户端的cookie里,这样,我们每个页面都从这个cookie里获得用户是否登录的信息,从而达到记录状态,验证用户的目的。但是,你真的会用cookie吗?下面是使用cookie的一些原则。

千万不要在cookie中存放用户的密码。加密的密码都不行。因为这个密码可以被人获取并尝试离线穷举。所以,你一定不能把用户的密码保存在cookie中。我看到太多的站点这么干了。
关于设计“记住密码”。一般的设计是当用户勾选了这个功能,系统会生成一个cookie,cookie包括用户名和一个固定的散列值,这个固定的散列值一直使用。这样,你就可以在所有的设备和客户上都可以登录,而且可以有多个用户同时登录。

2.cookie

在cookie中,保存三个东西——用户名,登录序列,登录token。
用户名:明文存放。
登录序列:一个被MD5散列过的随机数,仅当强制用户输入口令时更新(如:用户修改了口令)。
登录token:一个被MD5散列过的随机数,仅一个登录session内有效,新的登录session会更新它。
上述三个东西会存在服务器上,服务器的验证用户需要验证客户端cookie里的这三个事。

3.登录逻辑

  • (1)首次登录时,后端服务器判断用户账号密码正确之后,根据用户id、用户名、定义好的秘钥、过期时间生成 token ,返回给前端;
  • (2)前端拿到后端返回的 token ,存储在 localStorage 和 Vuex 里
  • (3)前端每次路由跳转,判断 localStorage 有无 token ,没有则跳转到登录页,有则请求获取用户信息,改变登录状态;
  • (4)每次请求接口,在 Axios 请求头里携带 token;
  • (5)后端接口判断请求头有无 token,没有或者 token 过期,返回401
    前端得到 401 状态码,重定向到登录页面。

3.前端登录(vue)

3.1在axios请求头里携带

使用 respone 拦截器,对 2xx 状态码以外的结果进行拦截。

if (window.localStorage.getItem('token')) {
  Axios.defaults.headers.common['Authorization'] = `Bearer ` + window.localStorage.getItem('token')
}

3.2判断状态码

如果状态码是401,则有可能是 Token 过期,跳转到登录页

instance.interceptors.response.use(
  response => {
    return response
  },
  error => {
    if (error.response) {
      switch (error.response.status) {
        case 401:
          router.replace({
            path: 'login',
            query: { redirect: router.currentRoute.fullPath } // 将跳转的路由path作为参数,登录成功后跳转到该路由
          })
      }
    }
    return Promise.reject(error.response)
  }
)

3.3进行路由守卫拦截

localStorage 里有 Token ,就调用获取 userInfo 的方法,并继续执行,如果没有 Token ,调用退出登录的方法,重定向到登录页。

router.beforeEach((to, from, next) => {
  let token = window.localStorage.getItem('token')
  if (to.meta.requiresAuth) {
    if (token) {
      store.dispatch('getUser')
      next()
    } else {
      store.dispatch('logOut')
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    }
  } else {
    next()
  }
})

3.4Vuex部分

3.4.1在 vuex的mutation_types 里定义:

export const LOGIN = 'LOGIN' // 登录
export const USERINFO = 'USERINFO' // 用户信息
export const LOGINSTATUS = 'LOGINSTATUS' // 登录状态

3.4.2然后在 mutation 里使用它们:

const mutations = {
  [types.LOGIN]: (state, value) => {
    state.token = value
  },
  [types.USERINFO]: (state, info) => {
    state.userInfo = info
  },
  [types.LOGINSTATUS]: (state, bool) => {
    state.loginStatus = bool
  }
}

3.4.3在request.js里定义接口

export const login = ({ loginUser, loginPassword }) => {
  return instance.post('/login', {
    username: loginUser,
    password: loginPassword
  })
}

export const getUserInfo = () => {
  return instance.get('/profile')
}

3.4.4在vuex的actions里引入

import * as types from './types'
import { instance, login, getUserInfo } from '../api'

3.4.5定义actios

export default {
  toLogin ({ commit }, info) {
    return new Promise((resolve, reject) => {
      login(info).then(res => {
        if (res.status === 200) {
          commit(types.LOGIN, res.data.token) // 存储 token
          commit(types.LOGINSTATUS, true)     // 改变登录状态为 
          instance.defaults.headers.common['Authorization'] = `Bearer ` + res.data.token // 请求头添加 token
          window.localStorage.setItem('token', res.data.token)  // 存储进 localStorage
          resolve(res)
        }
      }).catch((error) => {
        console.log(error)
        reject(error)
      })
    })
  },
  getUser ({ commit }) {
    return new Promise((resolve, reject) => {
      getUserInfo().then(res => {
        if (res.status === 200) {
          commit(types.USERINFO, res.data) // 把 userInfo 存进 Vuex
        }
      }).catch((error) => {
        reject(error)
      })
    })
  },
  logOut ({ commit }) { // 退出登录
    return new Promise((resolve, reject) => {
      commit(types.USERINFO, null)        // 情况 userInfo
      commit(types.LOGINSTATUS, false)  // 登录状态改为 false
      commit(types.LOGIN, '')          // 清除 token
      window.localStorage.removeItem('token')
    })
  }
}

4.后端登录逻辑(express)

4.1安装 express-session中间件

npm install  express-session
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-11-18 11:30:16  更:2021-11-18 11:31:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年7日历 -2024/7/3 22:04:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码