当前位置: 首页 > news >正文

vue基于Cookies实现记住密码自动登录功能

vue基于Cookies实现记住密码自动登录功能

Cookies 和localStorage存储比对

实现记住密码功能时,使用 Cookies 和使用 localStorage 各有其优势和考虑因素,具体需要取决于需求和安全考量:
在这里插入图片描述

1、Cookies 的优势:

  1. 广泛支持:Cookies 是 HTTP 协议的一部分,因此在几乎所有的浏览器和 Web 应用程序中都有良好的支持。
  2. 服务器端处理:可以通过设置 Cookie 的过期时间来实现自动登录功能,因为浏览器会在过期时间之前自动发送该 Cookie。这使得记住密码的实现变得相对简单。
  3. 可配置性:可以通过设置 Cookie 的属性(如过期时间、域名、路径等)来控制其在不同情况下的行为,例如只在 HTTPS 连接中发送、只在特定域名下可用等。
  4. 与服务器端状态同步:在某些情况下,特别是涉及到跨站点状态共享或服务器端状态跟踪时,Cookies 可以更自然地与服务器端的状态同步。

2、localStorage 的优势:

  1. 本地存储:localStorage 存储在用户的浏览器中,相比于 Cookies,更难以通过网络请求访问,从而提供了更好的安全性。
  2. 容量较大:localStorage 的存储容量通常比 Cookies 大得多(大约5MB左右),这使得它更适合存储大量的用户信息或配置数据。
  3. 更简单的 API:使用 localStorage 比起操作 Cookies 更加简单和直观,因为它提供了简洁的 key-value 存储接口。

3、综合考虑:

  • 安全性:对于敏感数据如密码,localStorage 通常被认为比 Cookies 更安全,因为它不会在每个 HTTP 请求中自动发送给服务器。
  • 便捷性:Cookies 更适合需要与服务器端状态同步或通过 HTTP 请求进行状态管理的场景,而 localStorage 更适合客户端本地的长期数据存储。
  • 合规性:在 GDPR 等隐私法规的要求下,需要谨慎处理用户数据。Cookies 的使用受到更严格的监管和规范。

综上所述,选择使用 Cookies 还是 localStorage 实现记住密码功能取决于具体需求,特别是安全性、数据大小和与服务器的交互方式等方面的考量。

4、用户登录信息加密

因为每个 Cookie 的大小限制在 4KB 到 8KB 之间。这包括了 Cookie 的名称、值以及其他元数据(如域名、路径、过期时间等)。浏览器对单个域名可以存储的 Cookie 数量也有限制,通常在几百个到几千个之间。

所以对用户信息进行前端cookies进行存储时,需要提取关键信息,此方案实现只对用户密码进行公钥加密,对用户其他的非关键信息进行自定义加密函数

5、主要加密函数示例

// auth.js
import Cookies from 'js-cookie';
import CryptoJS from 'crypto-js';
const Base64 = require('js-base64').Base64;
const EncryptionKey = 'encryptionKey';
// 加密
export const encrypt = word => {if (word == '' || word === undefined) {return '';}word = Base64.encode(word);var key = CryptoJS.enc.Utf8.parse(EncryptionKey);var srcs = CryptoJS.enc.Utf8.parse(word);var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});return Base64.encode(encrypted.toString());
};// 解密
export const decrypt = word => {if (word == '' || word === undefined) {return '';}word = Base64.decode(word);var key = CryptoJS.enc.Utf8.parse(EncryptionKey);var decrypt = CryptoJS.AES.decrypt(word, key, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});return Base64.decode(CryptoJS.enc.Utf8.stringify(decrypt).toString());
};export function setCookie(name, value = '', seconds) {let expires = new Date(new Date() * 1 + seconds * 1000);Cookies.set(name, value, { expires });
}export function getCookieByName(name) {return Cookies.get(name);
}// 设置记住密码信息
export function setRememberInfo(info) {const newInfo = JSON.parse(JSON.stringify(info));const ecKey = 'abcdefg1234567xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; // 公钥加密KEYnewInfo.pwd = encryptFn(ecKey, newInfo.pwd);const encryptInfo = encrypt(JSON.stringify(newInfo));setCookie('rememberInfo_' + newInfo.deptId, encryptInfo, 2592000);
}// 公钥密码加密
export function encryptFn(publicKey, data) {const crypto = require('crypto');// 使用公钥加密const publicKeyStr = '-----BEGIN PUBLIC KEY-----\n' + publicKey + '\n' + '-----END PUBLIC KEY-----';const encryptStr = crypto.publicEncrypt({ key: publicKeyStr, padding: crypto.constants.RSA_PKCS1_PADDING },Buffer.from(data, 'utf8'));const encrypted = encryptStr.toString('base64');return encrypted;
}

6、逻辑处理

1、在用户登录判断是否选了记住密码,如果勾选进行正常流程登录,并将用户信息记录用加密函数对主要信息进行信息加密存储在cookies中,看需要设置过期时间等其他cookies配置项。

2、用户重新进入登录页时、判断cookies中是否存在对应的用户信息,如果存在进行解密。拿出用户信息。

3、拿到的用户信息存在公钥加密的关键信息,比如用户密码,需要后端提供接口传递用户信息参数,后端使用私钥解密,校验用户信息是否匹配。如果匹配,一般接口返回包含token的成功响应。

4、已经拿到token了,就可以进行正常登录的后续流程实现自动登录了。

5、退出登录时,需要清除对应Cookies。

7、自动登录流程图

file

8、完整代码示例

只包含关键处理

<template><!-- 登录首页 --><div><!-- 登录表单 --><el-form ref="loginForm" :model="loginForm" :rules="loginRules" auto-complete="on" label-position="left"><el-form-item prop="userName"><el-input placeholder="请输入用户名" v-model="loginForm.userName"><i slot="prefix" class="el-input__icon iconfont icon-yonghu-filled"></i></el-input></el-form-item><el-form-item prop="password"><el-input placeholder="请输入密码" type="password" v-model="loginForm.password"><i slot="prefix" class="el-input__icon iconfont icon-mima-filled"></i></el-input></el-form-item><el-form-item prop="captcha" v-if="captchaType == '2'"><el-input placeholder="请输入验证码" v-model="loginForm.captcha" maxlength="10"><i slot="prefix" class="el-input__icon iconfont icon-yanzheng-filled"></i><img class="image_code" slot="suffix" :src="verifyKey" alt /></el-input></el-form-item></el-form><div><el-checkbox v-model="isRemember">记住密码</el-checkbox></div><el-button type="primary" @click.prevent="loginRequest()">登录</el-button></div>
</template><script>
import { loginRequest } from '@/api/user';
import { setToken, decrypt, encrypt, setRememberInfo } from '@/utils/auth';
import { getLoginInfoByRember } from '@/api/public/index';export default {data() {return {deptId: null,loginForm: {userName: '',password: '',captchaKey: '',captcha: '',keyId: ''},loginRules: {userName: [{ required: true, trigger: 'blur', message: '请输入用户名' }],password: [{ required: true, trigger: 'blur', message: '请输入密码' }]},publicKey: null,isRemember: false, //是否勾选记住密码userParams: {} // 需要存储的登录信息};},created() {this.deptId = this.$route.query.deptId;const rmInfo = this.getCookieByName('rememberInfo_' + this.deptId);if (rmInfo) {this.isRemember = true;this.getRememberInfo(rmInfo);}},methods: {// 根据记住密码获取登录信息getRememberInfo(remberInfo) {remberInfo = JSON.parse(decrypt(remberInfo));this.loginForm.userName = remberInfo.userName;const params = {userName: remberInfo.userName,password: remberInfo.pwd, // remberInfo.pwd是使用公钥加密的deptId: this.deptId// ......};getLoginInfoByRember(params) // 此请求接口为后端提供、对前端加密的密码进行验证.then(res => {// 校验成功、处理登录逻辑// 一般返回携带Token的响应,例如{ result:token:"2e7d220f2f60492b8835189d2d6f3463", .... }this.loginAfterOperate(res);}).catch(error => {// 校验失败、处理失败逻辑this.loginErrorOperate(error);});},// 获取加密keyinitKey() {return initKey().then(res => {if (res.code === 1000) {this.publicKey = res.result.publicKey;}});},// 正常登录处理async loginRequest() {await this.initKey();const params = {userName: this.loginForm.userName.trim(),password: encrypt(this.publicKey, this.loginForm.password)// 其他登录参数......};loginRequest(params).then(res => {if (this.isRemember) {this.userParams = { ...params, pwd: this.loginForm.password };setRememberInfo(this.userParams); // 存储用户登录信息Cookies}this.loginAfterOperate(res);}).catch(error => {this.loginErrorOperate(error);});},// 统一登录后处理async loginAfterOperate(res, params = null) {const { code, result } = res;if (code == 1000) {setToken(result.token);// 后续登录逻辑......}},// 统一登录异常处理async loginErrorOperate(error) {this.$message({ showClose: true, message: error.message, type: 'error', offset: 100 });// 其他逻辑......}}
};
</script>

本文由博客一文多发平台 OpenWrite 发布!

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Spring Boot外部配置加载顺序
  • Github报错:Kex_exchange_identification: Connection closed by remote host
  • Linux云计算 |【第一阶段】ENGINEER-DAY3
  • centos(或openEuler系统)安装kafka集群
  • 中文科技核心论文发表
  • java多线程等待唤醒机制详细介绍
  • [React]利用Webcomponent封装React组件
  • 【Python将字符串连接在一起】
  • Cadence23导入板框时的疑难杂症
  • SpringBoot3整合Druid报错Cannot load driver class: org.h2.Driver
  • 【芯片设计- RTL 数字逻辑设计入门 番外篇 12 -- SoC 设计中的 ECO】
  • 初识Docker及管理Docker
  • vue3 + antd vue 纯前端 基于xlsx 实现导入excel 转 json,将json数据转换XLSX并下载(下载模版)
  • 如何在空间计算领域赚钱
  • PgSQL报错“绑定消息提供了1个参数,但是已准备好语句““ 要求0个参数“
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • [译]如何构建服务器端web组件,为何要构建?
  • ➹使用webpack配置多页面应用(MPA)
  • 2017 年终总结 —— 在路上
  • Angularjs之国际化
  • cookie和session
  • css的样式优先级
  • exports和module.exports
  • gcc介绍及安装
  • leetcode-27. Remove Element
  • Linux Process Manage
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • PAT A1092
  • text-decoration与color属性
  • 高程读书笔记 第六章 面向对象程序设计
  • 工程优化暨babel升级小记
  • 构造函数(constructor)与原型链(prototype)关系
  • 猴子数据域名防封接口降低小说被封的风险
  • 利用jquery编写加法运算验证码
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 想使用 MongoDB ,你应该了解这8个方面!
  • 鱼骨图 - 如何绘制?
  • 翻译 | The Principles of OOD 面向对象设计原则
  • ​Redis 实现计数器和限速器的
  • ​低代码平台的核心价值与优势
  • # SpringBoot 如何让指定的Bean先加载
  • #Z0458. 树的中心2
  • $$$$GB2312-80区位编码表$$$$
  • (delphi11最新学习资料) Object Pascal 学习笔记---第13章第1节 (全局数据、栈和堆)
  • (void) (_x == _y)的作用
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • .bat批处理(二):%0 %1——给批处理脚本传递参数
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .Net Core缓存组件(MemoryCache)源码解析
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .net SqlSugarHelper
  • .net 调用海康SDK以及常见的坑解释
  • .NET 动态调用WebService + WSE + UsernameToken