前端常用的幾種加密方法實(shí)例demo
前言
在信息安全越來越受重視的今天,JS 安全一直是前端工程師們注重的大問題,前端的各種加密也變得更加重要。通常跟服務(wù)器的交互中,為保障數(shù)據(jù)傳輸?shù)陌踩?,避免被人抓包篡改?shù)據(jù),除了 https 的應(yīng)用,還需要對(duì)傳輸數(shù)據(jù)進(jìn)行加解密,保證了所有使用者的權(quán)益不被侵犯。
常見加密方式:
- 對(duì)稱加密算法(對(duì)稱加密算法是指加密和解密使用相同密鑰的加密算法。在前端常用的對(duì)稱加密算法包括 AES、DES 等。對(duì)稱加密算法的安全性依賴于密鑰,泄露密鑰就意味著任何人都可以對(duì)他們發(fā)送或接收的消息解密,所以密鑰的保密性對(duì)通信的安全性至關(guān)重要。對(duì)稱加密算法的優(yōu)點(diǎn)在于算法公開、計(jì)算量小、加密速度快、加密效率高,缺點(diǎn)在于在數(shù)據(jù)傳送前,發(fā)送方和接收方必須商定好密鑰,然后雙方保存好密鑰。如果一方的密鑰被泄露,那么加密信息也就不安全了。對(duì)稱加密算法適用于本地?cái)?shù)據(jù)加密、https 通信、網(wǎng)絡(luò)傳輸?shù)葓?chǎng)景。)
- Hash 算法(Hash 算法是一種將任意長(zhǎng)度的數(shù)據(jù)轉(zhuǎn)換成固定長(zhǎng)度的哈希值的算法。在前端常用的 Hash 算法包括 MD5、SHA-1 等。Hash 算法是不可逆的,因此常用于驗(yàn)證數(shù)據(jù)的完整性,例如文件校驗(yàn)和、密碼加密等。Hash 算法的優(yōu)點(diǎn)在于可以將任意長(zhǎng)度的數(shù)據(jù)轉(zhuǎn)換成固定長(zhǎng)度的哈希值,且計(jì)算速度快、效率高,缺點(diǎn)在于無法通過哈希值恢復(fù)原始數(shù)據(jù)。Hash 算法適用于數(shù)據(jù)完整性校驗(yàn)等場(chǎng)景。)
- 非對(duì)稱加密算法(非對(duì)稱加密算法是指加密和解密使用不同密鑰的加密算法,其中公鑰用于加密,私鑰用于解密。在前端常用的非對(duì)稱加密算法包括 RSA 等。非對(duì)稱加密算法的安全性依賴于公鑰和私鑰的生成和管理,泄露任何一把密鑰都意味著任何人都可以對(duì)他們發(fā)送或接收的消息解密,所以公鑰和私鑰的保密性對(duì)通信的安全性至關(guān)重要。非對(duì)稱加密算法的優(yōu)點(diǎn)在于可以保證數(shù)據(jù)傳輸?shù)陌踩裕秉c(diǎn)在于算法復(fù)雜、計(jì)算量大、加密速度慢、效率低。非對(duì)稱加密算法適用于數(shù)字簽名、身份認(rèn)證等場(chǎng)景。)
md5 加密(不可逆)
MD5 是比較常見的 Hash 算法,對(duì)于 MD5 而言,有兩個(gè)特性是很重要的,第一:明文數(shù)據(jù)經(jīng)過散列以后的值是定長(zhǎng)的;第二:是任意一段明文數(shù)據(jù),經(jīng)過散列以后,其結(jié)果必須永遠(yuǎn)是不變的。前者的意思是可能存在有兩段明文散列以后得到相同的結(jié)果,后者的意思是如果我們散列特定的數(shù)據(jù),得到的結(jié)果一定是相同的。
js-md5 加密方式 MD5 加密后的位數(shù)有兩種:16 位與 32 位。默認(rèn)使用 32 位。(16 位實(shí)際上是從 32 位字符串中取中間的第 9 位到第 24 位的部分)為提高安全性。根據(jù)業(yè)務(wù)需求,可以對(duì) md5 添加偏移量。如對(duì)原有字符拼接指定位數(shù)的字符串
npm 安裝
npm install --save js-md5
使用
// 然后在頁面中 引入 import md5 from 'js-md5' md5('加密內(nèi)容') //默認(rèn)32位 md5('加密內(nèi)容').substring(8, 24) // 從第8個(gè)字符開始截取16位
base64 位加密(可加密可解密)
Base64 是用于網(wǎng)絡(luò)上傳輸 8Bit 字節(jié)碼的最常見的編碼方法之一,Base64 不是安全領(lǐng)域的加密算法。實(shí)際上,Base64 只能算是一種編碼算法,對(duì)數(shù)據(jù)內(nèi)容進(jìn)行編碼以適應(yīng)傳輸。Base64 是一種將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為 ASCII 字符串的編碼方法。它將每 3 個(gè)字節(jié)的數(shù)據(jù)編碼為 4 個(gè)可打印的 ASCII 字符,因此 Base64 編碼后的數(shù)據(jù)長(zhǎng)度總是原數(shù)據(jù)長(zhǎng)度的約 4/3 倍(不足 4 的倍數(shù)時(shí)進(jìn)行補(bǔ)位)。Base64 編碼表由 64 個(gè)字符組成,其中包含大小寫字母、數(shù)字和兩個(gè)特殊字符 “+”, “/”,同時(shí)還有一個(gè)填充字符 “=”。Base64 編碼是一種可逆操作,可以通過解碼操作還原原始數(shù)據(jù)。
npm 安裝
npm install --save js-base64
使用
/** * BASE64加密 * @param str * @returns {string} */ base64Encode(str) { return btoa(unescape(encodeURIComponent(str))) } /** * BASE64解密 * @param str * @returns {string} */ base64Decode(str) { return decodeURIComponent(escape(atob(str))) }
RSA 加密(公鑰加密,私鑰解密)
RSA 加密:RSA 是一種非對(duì)稱加密算法,它使用公鑰和私鑰進(jìn)行加密和解密。在前端使用 RSA 加密時(shí),需要使用第三方庫(kù)進(jìn)行加密和解密操作,例如 jsencrypt。RSA 加密適用于加密大量數(shù)據(jù)或進(jìn)行數(shù)字簽名等場(chǎng)景。
// 使用公鑰加密 var publicKey = 'public_key_123' var encrypt = new JSEncrypt() encrypt.setPublicKey(publicKey) var encrypted = encrypt.encrypt('Hello World') // 使用私鑰解密 var privateKey = 'private_key_123' var decrypt = new JSEncrypt() decrypt.setPrivateKey(privateKey) var uncrypted = decrypt.decrypt(encrypted)
AES 加密(需要密鑰才能解密)
AES 加密:AES 是一種對(duì)稱加密算法,它使用相同的密鑰進(jìn)行加密和解密。在前端使用 AES 加密時(shí),需要使用第三方庫(kù)進(jìn)行加密和解密操作,例如 crypto-js。AES 加密適用于加密大量數(shù)據(jù)或進(jìn)行對(duì)稱加密等場(chǎng)景。
var CryptoJS = require('crypto-js') var data = { id: 1, text: 'Hello World' } // 加密生成密文 var ciphertext = CryptoJS.AES.encrypt( JSON.stringify(data), 'secret_key_123' ).toString() // 解密得到明文 var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret_key_123') var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8))
CryptoJS
CryptoJS 是一個(gè) JavaScript 的加解密的工具包。它支持多種算法:MD5、SHA1、SHA2、SHA3、RIPEMD-160 的哈希散列,以及進(jìn)行 AES、DES、Rabbit、RC4、Triple DES 加解密。
npm 安裝
npm install crypto-js
封裝加密文件 asc.js
// 1.引入CryptoJS加密插件 import CryptoJS from 'crypto-js' // 2.設(shè)置秘鑰和偏移量需要和后端一致 // 十六位十六進(jìn)制數(shù)作為密鑰 const KEY = CryptoJS.enc.Utf8.parse('wtkjtobacco12345') // 十六位十六進(jìn)制數(shù)作為密鑰偏移量 const IV = CryptoJS.enc.Utf8.parse('123456wtkj654321') export default { /** * 加密方法 * @param {*} word * @param {*} keyStr * @param {*} ivStr */ encrypt(word, keyStr, ivStr) { let key = KEY let iv = IV if (keyStr) { key = CryptoJS.enc.Utf8.parse(keyStr) iv = CryptoJS.enc.Utf8.parse(ivStr) } let srcs = CryptoJS.enc.Utf8.parse(word) var encrypted = CryptoJS.AES.encrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding, }) return CryptoJS.enc.Base64.stringify(encrypted.ciphertext) }, /** * 解密方法 * @param {*} word * @param {*} keyStr * @param {*} ivStr */ decrypt(word, keyStr, ivStr) { let key = KEY let iv = IV if (keyStr) { key = CryptoJS.enc.Utf8.parse(keyStr) iv = CryptoJS.enc.Utf8.parse(ivStr) } let base64 = CryptoJS.enc.Base64.parse(word) let src = CryptoJS.enc.Base64.stringify(base64) let decrypt = CryptoJS.AES.decrypt(src, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding, }) let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8) return decryptedStr.toString() }, }
在登錄組件 login.vue 使用
<template> <div class="home"> <el-form :model="userForm" status-icon :rules="rules" ref="userForm" label-width="100px" class="demo-userForm" label-position="top" > <el-form-item prop="phone"> <el-input type="text" v-model="userForm.phone" prefix-icon="el-icon-user" placeholder="請(qǐng)輸入用戶名" > </el-input> </el-form-item> <el-form-item prop="password" style="margin-top: 20px !important"> <el-input type="password" v-model="userForm.password" show-password prefix-icon="el-icon-goods" placeholder="請(qǐng)輸入密碼" > </el-input> </el-form-item> </el-form> <el-button @click="submitForm('userForm')">登錄</el-button> </div> </template> <script> import asc from "@/plugins/asc"; //引入封裝好的加密 export default{ name:'login', data(){ return{ // 表單綁定數(shù)據(jù) userForm: { phone: "", password: "", }, encryptionFrom: {}, //加密表單 // 校驗(yàn)規(guī)則 rules: { phone: [{ required: true, message: "賬號(hào)不能為空!" }], password: [{ required: true, message: "密碼不能為空!" }], }, } } methods:{ // 登錄按鈕事件 submitForm(formName) { this.$refs[formName].validate((valid) => { // this.$router.push({ name: "tobaccoBureau" }); if (valid) { this.loading = true; this.encryptionFrom = JSON.parse(JSON.stringify(this.userForm)); // 加密 this.encryptionFrom.password = asc.encrypt(this.userForm.password); this.$axios({ url: `auth/login`, method: "POST", params: this.encryptionFrom, }) .then(async (res) => { if (res.success) { if (this.isRemenberPassword) { // 判斷是否勾選了記住密碼 this.saveLocalPassword(); } else { localStorage.removeItem("localPassword"); } console.log("res", res); sessionStorage.setItem("token", res.data.token);//存儲(chǔ)token await this.$store.dispatch("getUserInfo"); // this.$router.push({ name: "case" }); // this.$message.success("登錄成功"); } }) .catch((err) => {}) .finally(() => { this.loading = false; }); } }); }, //保存緩存密碼 saveLocalPassword() { console.log("保存", this.form); localStorage.setItem("localPassword", JSON.stringify(this.form)); }, // 獲取緩存密碼 getLocalPassword() { this.isRemenberPassword = false; let form = JSON.parse(localStorage.getItem("localPassword")); if (form) { this.isRemenberPassword = true; this.form = form; } }, } } </script>
常用的加密方式–demo
<template> <div class="main"> <el-form :model="form" :rules="rules" ref="dialog_form" label-width="80px"> <el-row> <el-col :span="6"> <el-form-item label="密碼:"> <el-input placeholder="請(qǐng)輸入" size="small" v-model="form.password" @change="passwordChange" ></el-input> </el-form-item> </el-col> </el-row> <el-row >----------------------------------------------------------------------------------------------------------------</el-row > <el-row> <h1 class="title">md5加密(默認(rèn)32位)</h1> <span>{{ md5Encode(form.password) }}</span> </el-row> <el-row> <h1 class="title">md5加密(16位)</h1> <span>{{ md5Encode2(form.password) }}</span> </el-row> <el-row> <span class="detail" >js-md5加密方式 MD5 加密后的位數(shù)有兩種:16 位與 32 位。默認(rèn)使用 32 位。 (16 位實(shí)際上是從 32 位字符串中取中間的第 9 位到第 24 位的部分)為提高安全性。根據(jù)業(yè)務(wù)需求,可以對(duì) md5 添加偏移量。如對(duì)原有字符拼接指定位數(shù)的字符串。</span > </el-row> <el-row> <h1 class="title">base64加密(方法1 window.btoa)</h1> <span>{{ base64Encode1(form.password) }}</span> </el-row> <el-row> <h1 class="title">base64加密(方法3 Base64.encode使用插件)</h1> <span>{{ base64Encode2(form.password) }}</span> </el-row> <el-row> <h1 class="title"> base64加密(方法3 btoa(unescape(encodeURIComponent))) </h1> <span>{{ base64Encode3(form.password) }}</span> </el-row> <el-row> <h1 class="title"> base64解密(方法3 decodeURIComponent(escape())使用插件) </h1> <span>{{ base64Decode(base64Encode3(form.password)) }}</span> </el-row> <el-row> <h1 class="title">asc加密(使用CryptoJS插件)</h1> <span>{{ encrypt(form.password) }}</span> </el-row> <el-row> <h1 class="title">asc解密(使用CryptoJS插件)</h1> <span>{{ decrypt(encrypt(form.password)) }}</span> </el-row> <el-row> <span class="detail"> CryptoJS 是一個(gè) JavaScript 的加解密的工具包。它支持多種算法:MD5、SHA1、SHA2、SHA3、RIPEMD-160 的哈希散列,以及進(jìn)行 AES、DES、Rabbit、RC4、Triple DES 加解密。</span > </el-row> <el-row> <h1 class="title">對(duì)稱(RSA)加密:jsencrypt</h1> <span>{{ RSAEncode(form.password) }}</span> </el-row> <el-row> <el-col :span="14"> <span class="detail"> 關(guān)于該加密模塊,出現(xiàn)在自己做的一個(gè)后臺(tái)管理系統(tǒng)項(xiàng)目中,前端是vue,后端是Java。應(yīng)用的場(chǎng)景是需要前端通過公鑰對(duì)需要加密的密文進(jìn)行加密,后端通過私鑰對(duì)前端加密的密文進(jìn)行解密。這樣能比之前三個(gè)能極大的提高密文安全性。相關(guān)的使用方式可以參照下面 關(guān)于前端的其他加密解密好文中的第二個(gè)。 這里把關(guān)于前端方面簡(jiǎn)化后的代碼貼在下方,可供參考,后端方面的參考下方鏈接的第二個(gè)博文 </span> </el-col> </el-row> <div></div> </el-form> </div> </template> <script> import md5 from 'js-md5' //引入md5加密插件 import { Base64 } from 'js-base64' //base64加密插件 import CryptoJS from 'crypto-js' //引入CryptoJS加密插件 import JSEncrypt from 'jsencrypt' //引入JSEncrypt加密插件 export default { data() { return { form: { password: '123', //密碼 }, rules: {}, //校驗(yàn) } }, methods: { passwordChange() {}, // md5加密(默認(rèn)32位) md5Encode(str) { return md5(str) }, // 使用 MD5 加密算法進(jìn)行16位加密 md5Encode2(str) { return md5(str).substring(8, 24) // 從第8個(gè)字符開始截取16位 }, // base64加密(方法1--window.btoa) base64Encode1(str) { return window.btoa(str) }, // base64加密(方法2-- Base64.encode) 使用插件 base64Encode2(str) { return Base64.encode(str) }, // base64加密(方法3--window.btoa) /** * BASE64加密 * @param str * @returns {string} */ base64Encode3(str) { return btoa(unescape(encodeURIComponent(str))) }, /** * BASE64解密 * @param str * @returns {string} */ base64Decode(str) { return decodeURIComponent(escape(atob(str))) }, // asc加密 /** * 加密方法 * @param {*} word * @param {*} keyStr * @param {*} ivStr */ encrypt(word, keyStr, ivStr) { // 設(shè)置秘鑰和偏移量需要和后端一致 // 十六位十六進(jìn)制數(shù)作為密鑰 const KEY = CryptoJS.enc.Utf8.parse('123456jmff654321') // 十六位十六進(jìn)制數(shù)作為密鑰偏移量 const IV = CryptoJS.enc.Utf8.parse('654321jmff123456') let key = KEY let iv = IV if (keyStr) { key = CryptoJS.enc.Utf8.parse(keyStr) iv = CryptoJS.enc.Utf8.parse(ivStr) } let srcs = CryptoJS.enc.Utf8.parse(word) var encrypted = CryptoJS.AES.encrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding, }) return CryptoJS.enc.Base64.stringify(encrypted.ciphertext) }, // asc解密 /** * 解密方法 * @param {*} word * @param {*} keyStr * @param {*} ivStr */ decrypt(word, keyStr, ivStr) { // 設(shè)置秘鑰和偏移量需要和后端一致 // 十六位十六進(jìn)制數(shù)作為密鑰 const KEY = CryptoJS.enc.Utf8.parse('123456jmff654321') // 十六位十六進(jìn)制數(shù)作為密鑰偏移量 const IV = CryptoJS.enc.Utf8.parse('654321jmff123456') let key = KEY let iv = IV if (keyStr) { key = CryptoJS.enc.Utf8.parse(keyStr) iv = CryptoJS.enc.Utf8.parse(ivStr) } let base64 = CryptoJS.enc.Base64.parse(word) let src = CryptoJS.enc.Base64.stringify(base64) let decrypt = CryptoJS.AES.decrypt(src, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding, }) let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8) return decryptedStr.toString() }, // 非對(duì)稱加密密鑰生成網(wǎng)站:http://web.chacuo.net/netrsakeypair // RSA非對(duì)稱加密是一種廣泛使用的加密算法,它使用兩個(gè)密鑰:一個(gè)公鑰用于加密數(shù)據(jù),一個(gè)私鑰用于解密數(shù)據(jù)。在JavaScript中,可以使用CryptoJS庫(kù)來實(shí)現(xiàn)RSA非對(duì)稱加密。 // 非對(duì)稱(RSA)加密:jsencrypt RSAEncode(str) { let encryptor = new JSEncrypt() // 新建JSEncrypt對(duì)象 let publicKey = `MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuY3BqJVVeLwYF/qk6VeM ZNKruSQUfAsrz3Hv0ExmK7FdlsgtEBRMpFNylCFw2pbhdFtC0iedr5+DDKqqasUh boXMRR5KV27Zan96RbyQaqT9oXP6n9d6JBPNxuTglLtnK+FielB8oXmlz8YmOvs6 mH2n6GNoYAFwaNMXPAtiNFk+BbyTeN7t6aejQiidqq8OW87c/B6KD1ffbQBC56u2 CGYHPHjvL4G7QtR3vheXFNXjz2e0iVvHZ5hv/rBXRk9XNnV0eID3/TXlGiCFcyqd wm6tMV54H9tv9XX00NqhBnKtPIxLTCe5Ys/83K+KuniOYYtLQmy5NLgNaNTm6hCD ZwIDAQAB` //設(shè)置公鑰,可以從上面的非對(duì)稱加密密鑰生成網(wǎng)站中得到 encryptor.setPublicKey(publicKey) // 將得到的公鑰通過setPbulicKey方法設(shè)置到JSEncrypt對(duì)象中 return encryptor.encrypt(str) // 對(duì)需要加密的數(shù)據(jù)進(jìn)行加密,rspPassWord就是加密密文 }, }, } </script> <style lang="scss" scoped> .main { width: 100%; height: 100%; padding: 10px; .banner { width: 800px; height: 600px; margin: 0 auto; box-sizing: border-box; border: 1px solid #ccc; } .title { font-size: 16px; // color: rgb(150, 15, 212); display: inline-block; } .detail { color: darkgray; } } </style>
需要注意的是,前端加密并不能保證絕對(duì)的安全性,應(yīng)該結(jié)合其他安全措施來提高系統(tǒng)的安全性。同時(shí),在選擇加密算法時(shí)應(yīng)該根據(jù)具體的需求和場(chǎng)景進(jìn)行選擇,綜合考慮安全性和性能等因素。
總結(jié)
到此這篇關(guān)于前端常用的幾種加密方法的文章就介紹到這了,更多相關(guān)前端加密方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
不到30行JS代碼實(shí)現(xiàn)Excel表格的方法
這篇文章主要介紹了不到30行JS代碼實(shí)現(xiàn)Excel表格的方法,實(shí)現(xiàn)方法簡(jiǎn)單易懂,非常具有實(shí)用價(jià)值,可部分代替jQuery的功能,需要的朋友可以參考下2014-11-11小程序scroll-view組件實(shí)現(xiàn)滾動(dòng)的示例代碼
這篇文章主要介紹了小程序scroll-view組件實(shí)現(xiàn)滾動(dòng)的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-09-09Javascript讀取json文件方法實(shí)例總結(jié)
json文件是一種輕量級(jí)的數(shù)據(jù)交互格式,下面這篇文章主要給大家介紹了關(guān)于Javascript讀取json文件方法的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-11-11JS網(wǎng)頁播放聲音實(shí)現(xiàn)代碼兼容各種瀏覽器
JS網(wǎng)頁播放聲音有多種方法可以實(shí)現(xiàn),不過兼容各種瀏覽器的就沒有幾個(gè)了,不過本文的這個(gè)示例或許對(duì)大家有所幫助2013-09-09js實(shí)現(xiàn)實(shí)時(shí)刷新的三種形式(setInterval、WebSocket、EventSource)
本文主要介紹了js實(shí)現(xiàn)實(shí)時(shí)刷新的三種形式(setInterval、WebSocket、EventSource),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05JavaScript如何判斷一個(gè)對(duì)象是空對(duì)象(附5種常見方法)
在JavaScript中判斷對(duì)象的類型是開發(fā)過程中的一個(gè)常見需求,尤其是在處理不確定類型的數(shù)據(jù)時(shí),這篇文章主要介紹了JavaScript如何判斷一個(gè)對(duì)象是空對(duì)象的相關(guān)資料,需要的朋友可以參考下2025-04-04