vue登录 滑动验证,记住密码及AES加密解密

news2025/5/22 22:55:12

 相关依赖

npm install js-cookie  //js-cookie
npm install crypto-js  //AES加密解密
npm install -S vue-puzzle-vcode  //滑动验证

 vue2

<template>
  <div class="login">
    <div class="login-box">
      <div class="imgbox">
        <p class="title">安检设备管理系统</p>
      </div>
      <el-form
        ref="ruleForm"
        :rules="loginrules"
        label-width="0px"
        class="login-form"
        :model="loginForm"
      >
        <!-- 账号 -->
        <el-form-item prop="username">
          <el-input
            prefix-icon="el-icon-user"
            v-model="loginForm.username"
            placeholder="请输入账号"
          ></el-input>
        </el-form-item>
        <!-- 密码 -->
        <el-form-item prop="password">
          <el-input
            prefix-icon="el-icon-lock"
            v-model="loginForm.password"
            placeholder="请输入密码"
            show-password
          ></el-input>
        </el-form-item>
        <!-- 记住密码 -->
        <el-checkbox v-model="isRemenber">记住密码</el-checkbox>
        <!-- 按钮 -->
        <el-form-item class="btns">
          <el-button type="primary" @click="login">登录</el-button>
          <el-button type="info" @click="reset">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- 滑动验证功能 -->
    <Vcode
      :show="isVcodeShow"
      @success="successFn"
      @close="isVcodeShow = false"
    />
  </div>
</template>

<script>
//   import { openLoading, closeLoading } from "@/components/loading";
import Vcode from "vue-puzzle-vcode";
import axios from "axios";
import Cookies from "js-cookie";
import CryptoJS from "crypto-js";

export default {
  components: {
    Vcode,
  },
  data() {
    return {
      isRemenber: false, //记住密码
      isVcodeShow: false, // 验证码模态框是否出现
      //表单输入框
      loginForm: {
        username: "",
        password: "",
      },
      //表单验证
      loginrules: {
        username: [
          { required: true, message: "请输入账号", trigger: "blur" },
          {
            min: 3,
            max: 5,
            message: "账号长度在 3 到 5 个字符",
            trigger: "blur",
          },
        ],
        password: [
          { required: true, message: "请输入密码", trigger: "blur" },
          {
            min: 6,
            max: 15,
            message: "密码长度在 6 到 15 个字符",
            trigger: "blur",
          },
        ],
      },
    };
  },
  created() {
    this.init();
  },
  methods: {
    init() {
      const userInformation = Cookies.get("userInformation")
        ? Cookies.get("userInformation")
        : "";
      if (userInformation) {
        // 对密码进行解密
        this.loginForm = this.EncryptionDecryption(false, userInformation);
        // 将是否记住密码置为true
        this.isRemenber = true;
      } else {
        this.loginForm = {
          username: "",
          password: "",
        };
      }
    },
    //重置按钮
    reset() {
      //resetFields 重置为初始值
      this.$refs.ruleForm.resetFields();
    },
    //点击登录
    login() {
      //表单预验证
      //validate对表单进行验证第一个参数是布尔值 第二个参数是对象
      this.$refs.ruleForm.validate((valid) => {
        if (!valid) return;
        this.isVcodeShow = true;
      });
    },
    // 用户通过了验证
    successFn() {
      this.isVcodeShow = false; // 通过验证后,需要手动隐藏模态框
      // openLoading();
      this.callHttp();
    },
    async callHttp() {
      // const { data: res } = await this.$http.post("system/ssologin/Login", {
      //   username: this.loginForm.username,
      //   password: this.loginForm.password,
      // });

      // if (res.msg !== "登录成功") {
      //   //   closeLoading();
      //   return this.$message.error("登录失败,账号或密码不正确");
      // }
      this.$message.success("登录成功");

      // 登录成功后 判断是否选择了勾选密码
      if (this.isRemenber) {
        //将信息加到cookie
        Cookies.set(
          "userInformation",
          this.EncryptionDecryption(true, this.loginForm),
          {
            expires: 30, // 存储30天
          }
        );
      } else {
        // 删除cookie
        Cookies.remove("userInformation");
      }

      //将token加到cookies
      //   Cookies.set("token", res.data.token, {
      //     expires: 30, // 存储30天
      //   });

      //   // closeLoading();
      //   //跳转到home页面
      //   this.$router.push("/home");
    },

    //加密解密方法
    EncryptionDecryption(isEncrypt, data) {
      //秘钥
      let aesKey = "e10adc3949ba59abbe56e057f20f883e";

      //将秘钥转换成Utf8字节数组
      let key = CryptoJS.enc.Utf8.parse(aesKey);

      // 加密参数
      const option = {
        iv: CryptoJS.enc.Utf8.parse(aesKey.substr(0, 16)),
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7,
      };

      if (isEncrypt) {
        //加密
        let encrypt = CryptoJS.AES.encrypt(JSON.stringify(data), key, option);
        let encryptData = encrypt.toString();
        return encryptData;
      } else {
        //解密
        let decrypt = CryptoJS.AES.decrypt(data, key, option);
        let decryptData = JSON.parse(decrypt.toString(CryptoJS.enc.Utf8)); //解密后的数据
        return decryptData;
      }
    },
  },
};
</script>

<style lang="less" scoped>
.login {
  width: 100%;
  height: 100%;
  // background-image: url(../assets/veer-157272718.jpg);
  // background-repeat: no-repeat;
  // background-size: 100% 100%;
}
.login-box {
  width: 25%;
  background-color: white;
  border-radius: 5px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  border-radius: 10px;

  .imgbox {
    text-align: center;
    .title {
      padding: 20px 0;
      font-size: 25px;
      font-weight: 900;
    }
  }
  .login-form {
    width: 100%;
    padding: 0px 25px;
    box-sizing: border-box;
  }

  .btns {
    display: flex;
    justify-content: flex-end;
  }
}
</style>

 vue3+ts

<template>
  <div class="login">
    <div class="login-box">
      <div class="imgbox">
        <p class="title">{{ title }}</p>
      </div>
      <el-form
        ref="ruleFormRef"
        :rules="_data.loginrules"
        label-width="0px"
        class="login-form"
        :model="_data.loginForm"
      >
        <!-- 账号 -->
        <el-form-item prop="username">
          <el-input
            prefix-icon="User"
            v-model="_data.loginForm.username"
            placeholder="请输入账号"
          ></el-input>
        </el-form-item>
        <!-- 密码 -->
        <el-form-item prop="password">
          <el-input
            prefix-icon="Lock"
            v-model="_data.loginForm.password"
            placeholder="请输入密码"
            show-password
          ></el-input>
        </el-form-item>
        <!-- 记住密码 -->
        <el-checkbox v-model="_data.isRemenber">记住密码</el-checkbox>
        <!-- 按钮 -->
        <div class="btns">
          <el-button type="primary" @click="login(ruleFormRef)">登录</el-button>
          <el-button type="info" @click="reset(ruleFormRef)">重置</el-button>
        </div>
      </el-form>
    </div>
    <!-- 滑动验证功能 -->
    <Vcode :show="_data.isVcodeShow" @success="successFn" @close="closeFn" />
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive } from "vue";
import { useRouter, useRoute } from "vue-router";
import { onMounted } from "vue";
import type { FormInstance, FormRules } from "element-plus";
import { setToken, removeToken } from "@/util/auth";
import Vcode from "vue3-puzzle-vcode";
import Cookies from "js-cookie";
import CryptoJS from "crypto-js";

const router = useRouter();
const route = useRoute();

const title = ref(import.meta.env.VITE_APP_TITLE);
const ruleFormRef = ref<FormInstance>();

const _data = reactive({
  isRemenber: false, //记住密码
  isVcodeShow: false, // 验证码模态框是否出现
  //表单输入框
  loginForm: {
    username: "",
    password: "",
  },
  //表单验证
  loginrules: {
    username: [
      { required: true, message: "请输入账号", trigger: "blur" },
      {
        min: 3,
        max: 5,
        message: "账号长度在 3 到 5 个字符",
        trigger: "blur",
      },
    ],
    password: [
      { required: true, message: "请输入密码", trigger: "blur" },
      {
        min: 6,
        max: 15,
        message: "密码长度在 6 到 15 个字符",
        trigger: "blur",
      },
    ],
  },
});

onMounted(() => {
  init();
});

const init = () => {
  const userInformation = Cookies.get("userInformation")
    ? Cookies.get("userInformation")
    : "";
  if (userInformation) {
    // 对密码进行解密
    _data.loginForm = EncryptionDecryption(false, userInformation);
    // 将是否记住密码置为true
    _data.isRemenber = true;
  } else {
    _data.loginForm = {
      username: "",
      password: "",
    };
  }
};

//点击登录
const login = async (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  await formEl.validate((valid, fields) => {
    if (valid) {
      _data.isVcodeShow = true;
    } else {
      console.log("error submit!", fields);
    }
  });
};

// 通过了验证
const successFn = () => {
  _data.isVcodeShow = false; // 通过验证后,需要手动隐藏模态框
  callHttp();
};

const callHttp = async () => {
  // const { data: res } = await this.$http.post("system/ssologin/Login", {
  //   username: _data.loginForm.username,
  //   password: _data.loginForm.password,
  // });

  // if (res.msg !== "登录成功") {
  //   //   closeLoading();
  //   return this.$message.error("登录失败,账号或密码不正确");
  // }
  // this.$message.success("登录成功");

  // 登录成功后 判断是否选择了勾选密码
  if (_data.isRemenber) {
    //将信息加到cookie
    Cookies.set(
      "userInformation",
      EncryptionDecryption(true, _data.loginForm),
      {
        expires: 30, // 存储30天
      }
    );
  } else {
    // 删除cookie
    Cookies.remove("userInformation");
  }

  //将token加到cookies
  //   Cookies.set("token", res.data.token, {
  //     expires: 30, // 存储30天
  //   });

  // closeLoading();
  //跳转到home页面
  router.push("/home");
};

// 未通过了验证
const closeFn = () => {
  _data.isVcodeShow = false;
};

//重置按钮
const reset = (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  formEl.resetFields();
};

//加密解密方法
const EncryptionDecryption = (isEncrypt: Boolean, data: String | object) => {
  //秘钥
  let aesKey = "e10adc3949ba59abbe56e057f20f883e";

  //将秘钥转换成Utf8字节数组
  let key = CryptoJS.enc.Utf8.parse(aesKey);

  // 加密参数
  const option = {
    iv: CryptoJS.enc.Utf8.parse(aesKey.substr(0, 16)),
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7,
  };

  if (isEncrypt) {
    //加密
    let encrypt = CryptoJS.AES.encrypt(JSON.stringify(data), key, option);
    let encryptData = encrypt.toString();
    return encryptData;
  } else {
    //解密
    let decrypt = CryptoJS.AES.decrypt(data, key, option);
    let decryptData = JSON.parse(decrypt.toString(CryptoJS.enc.Utf8)); //解密后的数据
    return decryptData;
  }
};
</script>

<style lang="scss" scoped>
.login {
  width: 100%;
  height: 100%;
  // background-image: url(../assets/veer-157272718.jpg);
  // background-repeat: no-repeat;
  // background-size: 100% 100%;
  background-color: rgb(173, 255, 191);

  .login-box {
    width: 25%;
    background-color: white;
    border-radius: 5px;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    border-radius: 10px;

    .imgbox {
      text-align: center;
      .title {
        padding: 20px 0;
        font-size: 25px;
        font-weight: 900;
      }
    }
    .login-form {
      width: 100%;
      padding: 0px 25px;
      box-sizing: border-box;
    }

    .btns {
      display: flex;
      justify-content: flex-end;
      margin-bottom: 10px;
    }
  }
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1356140.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

进阶学习——Linux系统——程序和进程

目录 一、程序和进程的关系 1.程序 2.进程 2.1线程 2.2协程 3.进程与线程的区别 4.总结 4.1延伸 5.进程使用内存的问题 5.1内存泄漏——Memory Leak 5.2内存溢出——Memory Overflow 5.3内存不足——OOM&#xff08;out of memory&#xff09; 5.4进程使用内存出现…

听GPT 讲Rust源代码--compiler(11)

File: rust/compiler/rustc_mir_transform/src/simplify.rs 在Rust源代码中&#xff0c;rust/compiler/rustc_mir_transform/src/simplify.rs文件是Rust编译器中一系列进行MIR&#xff08;中间表示&#xff09;简化的转换的实现。MIR是Rust编译器中用于进行优化和代码生成的中间…

PDF.js实现搜索多个不同的关键词高亮显示效果

static\PDF\web\viewer.js 392行左右 // 自定义搜索关键词---------------------------------------- this.searchKeywords keyword > {if (typeof PDFViewerApplication ! undefined) {PDFViewerApplication.eventBus.dispatch(find, {query: keyword,caseSensitive: fal…

HTML5+CSS3⑥——CSS三大特性、表格、列表

CSS特性 继承性 层叠性 优先级 叠加计算规则 表格 表格结构标签 合并单元格 列表 无序列表 有序列表 定义列表

「数据结构」八大排序1

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;初阶数据结构 &#x1f387;欢迎点赞收藏加关注哦&#xff01; 文章目录 &#x1f349;插入排序&#x1f34c;直接插入排序&#x1f95d;复杂度及稳定性 &#x1f34c;希尔排序&#x1f95d;预…

Required request body is missing报错及解决

今天&#xff0c;我在尝试调用后端接口展示文章数据时遇到了错误&#xff0c;错误原因是请求体缺失&#xff0c; 但是我明明传了参数 然后我找了很久错误原因&#xff0c;发现在之前跟着写的一个差不多的功能时&#xff0c;请求方式是post 而我写的确是get 将get改为post后&…

【DevOps-06】Jenkins实现CI/CD操作

一、简要说明 基于Jenkins拉取GitLab的SpringBoot代码进行构建发布到测试环境实现持续集成 基于Jenkins拉取GitLab指定发行版本的SpringBoot代码进行构建发布到生产环境实现CD实现持续部署 二、准备Springboot工程 1、IDEA新建工程 2、填写项目工程信息 3、选择Springboot版本…

【MATLAB】EEMD_LSTM神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 EEMD-LSTM神经网络时序预测算法是一种结合了扩展经验模态分解&#xff08;EEMD&#xff09;和长短期记忆神经网络&#xff08;LSTM&#xff09;的时间序列预测方法。 EEMD是一种改进的EM…

Numpy基础

目录&#xff1a; 一、简介:二、array数组ndarray&#xff1a;1.array( )创建数组&#xff1a;2.数组赋值和引用的区别&#xff1a;3.arange( )创建区间数组&#xff1a;4.linspace( )创建等差数列&#xff1a;5.logspace( )创建等比数列&#xff1a;6.zeros( )创建全0数组&…

云消息队列 Kafka 版生态谈第一期:无代码转储能力介绍

作者&#xff1a;娜米 云消息队列 Kafka 版为什么需要做无代码转储 云消息队列 Kafka 版本身是一个分布式流处理平台&#xff0c;具有高吞吐量、低延迟和可扩展性等特性。它被广泛应用于实时数据处理和流式数据传输的场景。然而&#xff0c;为了将云消息队列 Kafka 版与其他数…

C++第四天

定义一个Person类&#xff0c;私有成员int age&#xff0c;string &name&#xff0c;定义一个Stu类&#xff0c;包含私有成员double *score&#xff0c;写出两个类的构造函数、析构函数、拷贝构造和拷贝赋值函数&#xff0c;完成对Person的运算符重载(算术运算符、条件运算…

使用Redis进行搜索

文章目录 构建反向索引 构建反向索引 在Begin-End区域编写 tokenize(content) 函数&#xff0c;实现文本标记化的功能&#xff0c;具体参数与要求如下&#xff1a; 方法参数 content 为待标记化的文本&#xff1b; 文本标记的实现&#xff1a;使用正则表达式提取全小写化后的…

特斯拉被比亚迪拉下神坛,马斯克难改命运岁月不如人

当这个消息浮现在我面前时&#xff0c;我几乎不敢相信眼前所见。比亚迪这个我曾无数次在文章中提及的中国车企&#xff0c;终于在2023年完成了伟大的历史任务——以销量突破特斯拉&#xff0c;站上全球电动车王座的宝座&#xff01; 过去我们都习惯于从欧美日韩那里听说汽车的成…

Go 编程必备:bufio 库的全面指南与实战技巧

Go 编程必备&#xff1a;bufio 库的全面指南与实战技巧 引言bufio 库概览bufio.Readerbufio.Writerbufio.Scanner 深入 bufio.Readerbufio.Reader 的基本使用高级功能应用场景 探索 bufio.Writerbufio.Writer 的基本使用高级功能应用场景 运用 bufio.Scannerbufio.Scanner 的基…

钉钉小程序生态7—企业机器人加互动卡片,改善用户体验的开始!

文章导航 钉钉小程序生态1—区分企业内部应用、第三方企业应用、第三方个人应用 钉钉小程序生态2—区分小程序和H5微应用 钉钉小程序生态3—钉钉扫码登录PC端网站 钉钉小程序生态4—钉钉小程序三方企业应用事件与回调 钉钉小程序生态5—钉钉群机器人消息通知和钉钉工作通知 钉…

React Admin 前端脚手架之ant-design-pro

文章目录 一、React Admin 前端脚手架选型二、React Admin 前端脚手架之ant-design-pro三、ant-design-pro使用步骤四、常用总结&#xff08;持续更新&#xff09;EditableProTable组件 常用组件EditableProTable组件 编辑某行后&#xff0c;保存时候触发发送请求EditableProTa…

Bayes贝叶斯识别Spam Email垃圾邮件

目录 介绍&#xff1a; 一、Gaussian Naive Bayes(连续型变量) 1.1数据处理 1.2建模 1.3cross_val_score函数评估 1.4classification_report函数评估 1.5classification_report函数和cross_val_score函数的区别 二、 Multinomial Naive Bayes&#xff08;离散型变量&…

软件工程专业毕业设计题目怎么选?

文章目录 0 简介1 如何选题2 最新软件工程毕设选题3 最后 0 简介 学长搜集分享最新的软件工程业专业毕设选题&#xff0c;难度适中&#xff0c;适合作为毕业设计&#xff0c;大家参考。 学长整理的题目标准&#xff1a; 相对容易工作量达标题目新颖 1 如何选题 最近非常多的…

[嵌入式C][入门篇] 快速掌握基础(9个语句)

开发环境&#xff1a; 网页版&#xff1a;跳转本地开发(Vscode)&#xff1a;跳转 文章目录 一、基础语法&#xff08;1&#xff09;if (如果)示例1: 普通使用 if示例2: 带否则 else示例3: 否则如果 else if &#xff08;2&#xff09;switch case (选择)规则示例1: &#xff0…

Arduino开发实例-EMG 肌肉信号传感器

EMG 肌肉信号传感器 文章目录 EMG 肌肉信号传感器1、EMG 肌肉信号传感器介绍2、硬件准备及接线3、代码实现1、EMG 肌肉信号传感器介绍 在医学研究中,测量肌肉的活动、收缩和扩张非常重要。 EMG 肌肉传感器测量肌肉活动并产生信号以显示扩张和收缩量。 因此,输出取决于所选肌…