如何解决java老开源系统登录密码在浏览器开发工具里暴露的问题

createh51周前 (03-27)技术教程5

网上找的若依开源框架,拿来登录密码直接暴露在浏览器开发工具里面,拿这个东西直接给甲方需求方,肯定过不了关的。

甲方假如哪天发现了这个问题,肯定会要求退工程款,拿来主义没问题,但是得优化。

包括另一个开源项目,号称用了Apache的Shiro安全框架,安全级别很高,但是也有同样的问题


开源老框架多半是个半成品。

但是也有最新的新框架,用最新java17,以及typeScript跑起来的项目就不存在这个问题,把账户和密码一起进行了加密传输:

但是我接到甲方的项目,用的是若依老框架开发的,业务逻辑写了一大堆代码,都在老框架里面,写完了,就回头看发现了这个密码暴露的问题。

客户虽然不提,但是我不能不解决。

项目中vue有个加解密原码

import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'

// 密钥对生成
http://web.chacuo.net/netrsakeypair

const publicKey = 'xxx'

const privateKey = 'xxx'

// 加密

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) // 对数据进行解密

}

但是这个只能在前端加解密,是为了保存在cookie里是密文。

发送登录请求的方法:

// 调用action的登录方法

userStore.login(loginForm.value).then(() => {

const query = route.query;

const otherQueryParams = Object.keys(query).reduce((acc, cur) => {

if (cur !== "redirect") {

acc[cur] = query[cur];

}

return acc;

}, {});

router.push({ path: redirect.value || "/", query: otherQueryParams });

}).catch(() => {

loading.value = false;

loginForm.value.code = null

loginForm.value.password = reverseData.reverse().join('');

// 重新获取验证码

if (captchaEnabled.value) {

getCode();

}

});

调用这个登录方法之前必须要给loginForm的password属性加密处理。

网上搜索“js加密密码,java解密”找了两篇博文

https://link.csdn.net/?from_id=146127027&target=https%3A%2F%2Fblog.51cto.com%2Fu_16213323%2F13179616

https://blog.csdn.net/qq_45089709/article/details/146044148

这两篇博文我用过了,不能说不能用,但是不适合我这个项目,我这个项目是用的java8,博客里要求可能是更高版本的java,我用的时候,后台直接报错,直接用不了。

我有想过把业务逻辑往新框架里面搬,但是如此耗费的工程,至少还要花一个月时间,甲方马上就结算工程款了,我可不想还要等一个月拿到钱。

再说甲方给的钱本来就不多,为了尽快变现,我必须另外再想办法。

甲方给的钱不多,就自己想一个简单加解密方法。

首先加密解密要有密码本,密码本就是一串字符串

在vue项目定义一个有16个字符常量字符串

const key = "xxxxxxxxxxx1234";

其次要有密码坐标,再定义个子元素是0到15数字的数组,数字顺序要打乱。

const indexArayy = [1,10,4,8,3,0,15,13,11,12,2,9,7,5,6,14]

再者必须要有密码规则,前段密码校验必须是6到16位,不能超过密码本的字符长度

password: [

{ required: true, trigger: "blur", message: "请输入您的密码" },

{

min: 6,

max: 16,

message: '密码长度在 6 到 16 个字符之间',

trigger: 'blur'

}

],

最后生成密文,生成的密文里面开头存放原文密码的字符串长度,

这样后端java就知道循环多少次进行解密了

先把原文密码字符串顺序倒置,变成字符串数组

let reverseData = loginForm.value.password.split('').reverse();

密码本(这里定义为变量key),也变成字符串数组

let split = key.split('');

最后将密码本里的字符串按照密码坐标进行替换,一个个替换为已经倒置的密码原文

for (let i = 0; i < reverseData.length; i++) {

split[indexArayy[i]] = reverseData[i];

}

如何保存密码长度呢?

为了保证密码长度是固定的两位数字,将密码长度乘以2,因为6*2=12,16*2=32,保证密码长度存储都是两位数,然后拼接到上面生成的密文的开头位置。

loginForm.value.password = reverseData.length*2+split.join('');

后端解密代码

先定义密码坐标数组常量,要跟前端一致

int [] indexArray = {1,10,4,8,3,0,15,13,11,12,2,9,7,5,6,14};

密码解密代码:

String password = loginBody.getPassword();

//后端密码解密

String substring = password.substring(0, 2);

String password1 = password.substring(2);//获取加密后的密码

int pwdLen= Integer.valueOf(substring)/2;//获取密码长度

StringBuffer stringBuffer = new StringBuffer();

for (int i = 0; i < pwdLen; i++) {

stringBuffer.append(password1.charAt(indexArray[i]));

}

String decrypted = stringBuffer.reverse().toString();//倒置字符串获取密码原文

因为甲方给了钱不多,就这样弄个简单的凑合用,虽然密码混在密文中还能看见,但是也很难破解。

现在要做的就是隐藏密码坐标,这个就相对简单了,

const indexArayy = [encryptNumber(2),

encryptNumber(5),

encryptNumber(13),

encryptNumber(8),

encryptNumber(3),

encryptNumber(0),

encryptNumber(15),

encryptNumber(4),

encryptNumber(11),

encryptNumber(12),

encryptNumber(10),

encryptNumber(9),

encryptNumber(7),

encryptNumber(1),

encryptNumber(6),

encryptNumber(14)]

对坐标中的每个元素进行加密,

然后取的时候再进行解密,

split[decryptNumber(indexArayy[i])] = reverseData[i];

js加密解密就很简单,逻辑自己写,网上随便找一个,推荐base64;

这样前端js混淆部署,就看不到坐标数字,这样就非常安全了。

原文密码123456加密后的密文为121h5246an3yue1234,如图

这样基本就解决问题了,但是呢Chrome浏览器里面有个自动存储密码功能,它存储的是密码的密文,所以也对系统起到保护作用,假如别人想通过Chrome浏览器找到密码原文也是找不到的。

相关文章

Java中字符串的长度值

我第一次知道:在 UTF - 8 编码中,英文字符和空格占 1 个字节,中文字符通常占 3 个字节。在 GBK 编码中,英文字符和空格占 1 个字节,中文字符占 2 个字节。上代码,看图: publi...

吊打面试官(十)--Java语言中字符串相关处理一文全掌握

导读在Java中,`String`、`StringBuilder`和`StringBuffer`是处理字符串的三个常用类。它们各有特点,适用于不同的场景。下面详细介绍它们的使用场景、区别、实现原理、使...

那些年我在数据库加密的大坑坑坑坑

之前在对数据库加密的需求中遇到一些坑,拿出来分享一下。加密的方案是:将数据使用AES加密再经过base64编码。最近整理了一些Java架构学习视频和大厂项目底层知识点,需要的同学欢迎私信我【Java】...

javascript超长知识归纳总结

基本概念javascript简称js,是一种脚本语言,用来操作HTML中的节点,产生动态效果。包括三大模块。ECMAScript:是javascript核心语法;json是其中一种轻量级的数据交换格式...

Java 8之后的那些新特性(二):文本块 Text Blocks

继续聊Java 8之后的新特性,这周我讲下Text Blocks这个特性。Text Blocks最开始是个JDK 14引进的,当时为预览版功能,在JDK 15中被正式确定。这意味着如果你想使用这个功能...