参考
问题描述
经常在管理程序中经常能看到 “记住密码” 和 “用户名和密码”登录的界面,如图:
问题:
- 如何保证下次进入项目能继续获取用户的账号和密码
- 登录账号和密码如果明文传输,如果懂前端开发,不就可以很容易获取账号和密码了吗,很不安全
如何保证下次进入项目能继续获取用户的账号和密码?
解决办法:如果用户选择“记住账号”,则将用户的输入内容保存到cookie中
如果直接保存账号和密码,那么用户可以很容易直接通过开发控制台查看账号和密码,很不安全,这个和直接用账户和密码直接登录明文传输的风险是一样的,不安全。
import Cookies from "js-cookie";
import {encrypt} from "@/util/jsencrypt";
export default {
created() {
this.getCookie();
},
methods: {
getCookie() {
const username = Cookies.get("username");
const password = Cookies.get("password");
const rememberMe = Cookies.get('rememberMe')
this.loginForm = {
username: username === undefined ? this.loginForm.username : username,
// 从cookie中获取密码,然后解密
password: password === undefined ? this.loginForm.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
code: "",
redomStr: "",
};
},
// 点击登录
handleLogin() {
// 如果是要记住密码
if (this.loginForm.rememberMe) {
Cookies.set("username", this.loginForm.username, {expires: 30});
// 对用户的输入加密,保存到cookie中
Cookies.set("password", encrypt(this.loginForm.password), {expires: 30});
Cookies.set('rememberMe', this.loginForm.rememberMe, {expires: 30});
} else { // 不记住密码
Cookies.remove("username");
Cookies.remove("password");
Cookies.remove('rememberMe');
}
// 提交登录信息
this.$store.dispatch("LoginByUsername", this.loginForm).then(() => {
}).catch(() => {
})
}
},
}
}
如何保证登录账号的安全?
解决办法:将用户登录的账号和密码加密,然后将加密的字符串提交给后端,后端然后解密字符串,获取用户的账号和密码,然后匹配登录
利用这个思路,同理,保存密码,也是可以将加密的字符串保存到cookie中,然后通过解密,获取到原始的账号和密码
加密和解密的过程,推荐使用 非对称加密
加密方式介绍
对称加密
简单理解就是加密和解密使用相同的秘钥,由于前端代码是完全暴露在外面的,某些人可以通过源码查找到秘钥,从而解密,因此不安全
- 定义crypto-js加密 / 解密 方法
import CryptoJS from 'crypto-js';
export default {
//随机生成指定数量的16进制key
generatekey(num) {
let library = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let key = "";
for (var i = 0; i < num; i++) {
let randomPoz = Math.floor(Math.random() * library.length);
key += library.substring(randomPoz, randomPoz + 1);
}
return key;
},
//加密
encrypt(word, keyStr) {
keyStr = keyStr ? keyStr : 'abcdsxyzhkj12345'; //判断是否存在ksy,不存在就用定义好的key
var key = CryptoJS.enc.Utf8.parse(keyStr);
var srcs = CryptoJS.enc.Utf8.parse(word);
var encrypted = CryptoJS.AES.encrypt(srcs, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
return encrypted.toString();
},
//解密
decrypt(word, keyStr) {
keyStr = keyStr ? keyStr : 'abcdsxyzhkj12345';
var key = CryptoJS.enc.Utf8.parse(keyStr);
var decrypt = CryptoJS.AES.decrypt(word, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 });
return CryptoJS.enc.Utf8.stringify(decrypt).toString();
}
}
- 测试
// var keys = AES.generatekey(16);
//如果是对象/数组的话,需要先JSON.stringify转换成字符串
// 不传key值,就默认使用上述定义好的key值
var encrypts = AES.encrypt(JSON.stringify(cars));
var dess = JSON.parse(AES.decrypt(encrypts));
// var encrypts = AES.encrypt('1234asdasd');
// var dess = AES.decrypt(encrypts);
console.log(encrypts)
console.log(encrypts.length)
console.log(dess)
非对称加密
公钥用来加密,任何人都知道,私钥在服务器,只有通过私钥可以解密密文,及时黑客拿到了公钥和密文,也无法解密
- JSEncrypt 加密 / 解密
import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
// 密钥对生成 http://web.chacuo.net/netrsakeypair
const publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcMTbFitfOemx/8tcasryDRQk3\n' +
'Y7Zp8szBM03xbH3s+umdI5blcUdPLs4NEH9qojFoiCb7nPg92MXEfaXy9gNZ7Qft\n' +
'OsU5XQRhySp6e/NdbRHut1ksvJXnlUc+OLFW6RIZgHwqmsZrlWRo71MXOBoPcpss\n' +
'VEFfqFmzDY0Nw7zUKQIDAQAB'
const privateKey = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANwxNsWK1856bH/y\n' +
'1xqyvINFCTdjtmnyzMEzTfFsfez66Z0jluVxR08uzg0Qf2qiMWiIJvuc+D3YxcR9\n' +
'pfL2A1ntB+06xTldBGHJKnp7811tEe63WSy8leeVRz44sVbpEhmAfCqaxmuVZGjv\n' +
'Uxc4Gg9ymyxUQV+oWbMNjQ3DvNQpAgMBAAECgYEAhU+Od58N9UaNdhGSRem81ETx\n' +
'xYUrJY4IhVgIcoha3SU0Vxz6+MLSh5Aw1BwO6IJ2I3F7GI76hIc/hS0FUcm8UI9r\n' +
'9QrDp9LC5lQjD8kjnLCRpKwF9fSv76asWHhKsvTDVZvsxJhuVKd6SSmFYSC5EgNx\n' +
'uVn5PeTLCYzpNtJ6IlkCQQD9FsGOilFltYiXZWNvfdsCCBmzOQUzmoU3G/WOQHyy\n' +
'3ue/cOYOmygDNjxm2aqBx6TAD7fs0ErnD6xnwgM6jgWnAkEA3rmXMjTgT7Ux5uE1\n' +
'RKwUvzVPZgyNt3mvabfTU6ROFD99Rbgf7nb6Fa1+DFKXu6mxoHE6mL5c/Z8mjyru\n' +
'fB4xrwJAFFAbQOGBHvSu/de5X11ukn8r8OKGtFmWj5HC56PtXj3dw9O/4zQ4xek4\n' +
'd9jIgpoPcwrP7EXbfSgY4ksED1MOyQJATMjrCVIVayVquNA3jx9MX8c/Qk1dpj17\n' +
'bhUD9DgW+wAQbjLWP14hRcv0QsdOrFIKfOfMbdBjOsTdhEomwf+e3QJBAI3y7+Z/\n' +
'+KWOirIjXsWmGZAJSBuF4v3s5mK9lMcBBkTUggz+MwAP9gbvWkSc0jpuMGGpigKE\n' +
'pUm/fr5oXLkGSAA='
// 加密
export function encrypt(txt) {
const encryptor = new JSEncrypt()
encryptor.setPublicKey(publicKey) // 设置公钥
return encryptor.encrypt(txt) // 对数据进行加密
}
// 解密
export function decrypt(txt) {
const encryptor = new JSEncrypt()
encryptor.setPrivateKey(privateKey) // 设置私钥
return encryptor.decrypt(txt) // 对数据进行解密
}