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

 相关依赖

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.mfbz.cn/a/295356.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

BOM介绍

文章目录 1、简介主要作用 2、BOM的组成2.1 窗口对象window2.1.1 window对象特点2.1.2 window作用域2.1.3 window对象常见方法**第一类&#xff1a;系统对话框**第二类&#xff1a;控制浏览器窗口方法第三类&#xff1a;与定时器有关的方法 1、简介 BOM&#xff08;Browser Ob…

面试算法98:路径的数目

题目 一个机器人从mn的格子的左上角出发&#xff0c;它每步要么向下要么向右&#xff0c;直到抵达格子的右下角。请计算机器人从左上角到达右下角的路径的数目。例如&#xff0c;如果格子的大小是33&#xff0c;那么机器人从左上角到达右下角有6条符合条件的不同路径。 分析…

教学/直播/会议触摸一体机定制_基于展锐T820安卓核心板方案

触控一体机是一种集先进的触摸屏、工控和计算机技术于一体的设备。它取代了传统的键盘鼠标输入功能&#xff0c;广泛应用于教学、培训、工业、会议、直播、高新科技展示等领域。触摸一体机的应用提升了教学、会议和展示的互动性和信息交流。 触摸一体机方案基于国产6nm旗舰芯片…

鸿蒙问题之本地模拟器无法识别

今天按例打开本地模拟器&#xff0c;发现DevEco Studio不能检测到我的本地模拟器了。 重启了DevEco Studio和模拟器多次都无果。果断删除模拟器 然后创建一个新的&#xff0c;就可以成功检测到了。这应该是idea的一个bug

外包干了5个月,技术明显退步了...

先说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入湖南某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年12月份&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测…

《知识扫盲》ROS和ROS2对比

文章摘选自&#xff1a;ROS与ROS2对比 1.ROS问题举例 ROS的设计目标是简化机器人的开发&#xff0c;如何简化呢&#xff1f;ROS为此设计了一整套通信机制&#xff08;话题、服务、参数、动作&#xff09;。 通过这些通信机制&#xff0c;ROS实现了将机器人的各个组件给的连接…

基于springboot的java读取文档内容(超简单)

读取一个word文档里面的内容&#xff0c;并取出来。 代码&#xff1a; SneakyThrowsGetMapping(value "/readWordDoc")ApiOperationSupport(order 1)ApiOperation(value "文档读取 ", notes "文档读取 ")public R ReadWordDoc () {System.o…

如何在 ChatGPT 上使用 Wolfram 插件回答数学问题

这里写自定义目录标题 写在最前面Wolfram是什么&#xff1f;ChatGPT 如何与 Wolfram 相结合&#xff0c;为什么有效&#xff1f;如何在 ChatGPT 上安装 Wolfram 插件&#xff1f; 写在最前面 参考&#xff1a;https://clickthis.blog/zh-CN/how-to-answer-math-questions-usin…

Codeium在IDEA里的3个坑

转载自Codeium在IDEA里的3个坑&#xff1a;无法log in&#xff0c;downloading language server和中文乱码_downloading codeium language server...-CSDN博客文章浏览阅读1.7w次&#xff0c;点赞26次&#xff0c;收藏47次。Codeium安装IDEA插件的3个常见坑_downloading codeiu…

arr.prototype 数组的方法

1.forEach 作用:遍历这个数组 代码&#xff1a; let arr [10, 20, 30, 40, 50];arr.forEach((item) > {console.log(item);}); 返回值:没有返回值 2.fiflter 作用:过滤数组 代码&#xff1a; let arr [10, 20, 30, 40, 50];let newArr arr.filter((item) > {retu…

Mysq之——分库分表

Mysq之——分库分表 简介分库分表的方式垂直分表垂直分库水平分库水平分表 图解&#xff1a;垂直分表与水平分表&#xff08;分库类似&#xff09;分库分表带来的问题 简介 分库分表就是为了解决由于数据量过大而导致数据库性能降低的问题&#xff0c;将原来独立的数据库拆分成…

应用层网络协议

tags: [“计算机网络”] descripution: “学习应用层的一些常用协议” 网络协议&#xff1a;约定的信息传输的格式&#xff0c;如几个字节是消息头、消息头记录什么信息之类的&#xff1b;c/s架构&#xff1a;不一定是两台计算机&#xff0c;而是两个应用、两个端口工具&#…

打破技术壁垒,低代码工具带您开启中小电商企业数字化时代

随着互联网技术的不断进步和智能手机的普及&#xff0c;越来越多的消费者选择在网络上购物&#xff0c;这不仅为传统零售业带来巨大冲击&#xff0c;也为中小型电商提供了宝贵的发展机遇。 商务部数据显示&#xff0c;2023年&#xff0c;电子商务持续推动消费恢复增长。1-11月…

异步http接口调用库:httpx

谈到http接口调用&#xff0c;Requests大家并不陌生&#xff0c;例如&#xff0c;robotframework-requests、HttpRunner等HTTP接口测试库/框架都是基于它开发。这里将介绍另一款http接口测试框架:httpx。 它的API和Requests高度一致。 github: GitHub - encode/httpx: A next…

StreamPark + PiflowX 打造新一代大数据计算处理平台

&#x1f680; 什么是PiflowX PiFlow 是一个基于分布式计算框架 Spark 开发的大数据流水线系统。该系统将数据的采集、清洗、计算、存储等各个环节封装成组件&#xff0c;以所见即所得方式进行流水线配置。简单易用&#xff0c;功能强大。它具有如下特性&#xff1a; 简单易用…

群晖Docker部署HomeAssistant容器结合内网穿透远程控制家中智能设备

目录 一、下载HomeAssistant镜像 二、内网穿透HomeAssistant&#xff0c;实现异地控制智能家居 三、使用固定域名访问HomeAssistant 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。 点击跳转到网站 Ho…

树低级(C语言版)

一.树基本计算规则 关于树的大部分知识点我们都讲过了&#xff0c;那么如果我给你树的节点&#xff0c;你可以算出叶子节点个数吗&#xff1f; 下面我们总结下一些计算规则&#xff1a; 1.父子计算规则&#xff1a; parent(child-1)/2; leftchildparent*21,rightchildpare…

设计循环队列——oj题622

. 个人主页&#xff1a;晓风飞 专栏&#xff1a;LeetCode刷题|数据结构|Linux 路漫漫其修远兮&#xff0c;吾将上下而求索 文章目录 题目要求&#xff1a;应该支持如下操作&#xff1a;示例&#xff1a;提示&#xff1a; 结构体定义队列的创建基本操作判断队列是否为空&#xf…

python 数据容器

数据容器概念 一个可以存储多个元素的python数据类型 python有的数据容器 list(列表) tuple(元组) str(字符串) set(集合) dct(字典) 列表 python的列表的数据类型可以是不同的 my_list ["1",123,True,[123,"3333",d,False]]for item in my_list:p…

第三部分使用脚手架:vue学习(61-65)

文章目录 61 创建vue脚手架![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/f71d4324be0542209e690ab9e886d199.png)62 分析脚手架结构63 render函数64 修改默认配置65 ref 属性 61 创建vue脚手架 写完vue文件&#xff0c;没有脚手架做翻译&#xff0c;浏览器不认识…