java web系统明文密码加密传输

 最近项目PL提出系统数据越权和明文密码传输问题,涉及网络安全的问题,这让我一脸懵逼,查阅相关资料后做相关记录

1. 数据越权:

      涉及重要功能需要验证用户是否当前用户操作,修改密码功能接口参数用户Id人员被恶意篡改,应该应用系统token缓存用户信息做修改密码操作

2. 明文密码    

1. 加密解密

1.1 前端js加密概述

对系统安全性要求比较高,那么需要选择https协议来传输数据。当然很多情况下一般的web网站,如果安全要求不是很高的话,用http协议就可以了。在这种情况下,密码的明文传输显然是不合适的,因为如果请求在传输过程中被截了,就可以直接拿明文密码登录网站了。 
HTTPS(443)在HTTP(80)的基础上加入了SSL(Secure Sockets Layer 安全套接层)协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。传输前用公钥加密,服务器端用私钥解密。

对于使用http协议的web前端的加密,只能防君子不能防小人。前端是完全暴露的,包括你的加密算法。 
知道了加密算法,密码都是可以破解的,只是时间问题。请看知乎上的一篇文章:对抗拖库

所以加密是为了增加破解的时间成本,如果破解需要花费的时间让人难以接受,这也就达到了目的。

而为了保证数据库中存储的密码更安全,则需要在后端用多种单向(非对称)加密手段混合进行加密存储。

前端加密后端又需要解密,所以需要对称加密算法,即前端使用 encrypted = encrypt(password+key),后端使用 password = decrypt(encrypted +key) ,前端只传输密码与key加密后的字符串encrypted ,这样即使请求被拦截了,也知道了加密算法,但是由于缺少key所以很难破解出明文密码。所以这个key很关键。而这个key是由后端控制生成与销毁的,用完即失效,所以即使可以模拟用加密后的密码来发请求模拟登录,但是key已经失效了,后端还是验证不过的。

注意,如果本地环境本就是不安全的,key被知道了,那就瞬间就可以用解密算法破解出密码了。这里只是假设传输的过程中被截获的情形。所以前端加密是防不了小人的。如果真要防,可以将加密算法的js文件进行压缩加密,不断更新的手段来使js文件难以获取,让黑客难以获取加密算法。变态的google就是这么干的,自己实现一个js虚拟机,通过不断更新加密混淆js文件让加密算法难以获取。这样黑客不知道加密算法就无法破解了。

常用的对称加密算法有DES、3DES(TripleDES)、AES、RC2、RC4、RC5和Blowfis。可以参考:常用加密算法的Java实现总结

这里采用js端与java端互通的AES加密算法。

1.2 前后端加密解密

1.2.1 引用的js加密库

Cryptojs下载

<script src="${request.contextPath}/resources/plugins/cryptojs.js"></script>

1.2.2 js加密解密

var srcs = CryptoJS.enc.Utf8.parse(‘666666’);

var key = CryptoJS.enc.Utf8.parse('o7H8uIM2O5qv65l2');//秘钥

function Encrypt(word){

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();

}

function Decrypt(word){

var decrypt = CryptoJS.AES.decrypt(word, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});

return CryptoJS.enc.Utf8.stringify(decrypt).toString();

}

这里key是页面加载的时候由服务器端生成的,用隐藏域保存。

1.2.3 Java端加密解密(PKCS5Padding与js的Pkcs7一致)

 

package com.jykj.demo.util;

import javax.crypto.Cipher;

import javax.crypto.KeyGenerator;

import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

import sun.misc.BASE64Decoder;

public class EncryptUtil {

private static final String KEY = "o7H8uIM2O5qv65l2";

private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";

public static String base64Encode(byte[] bytes){

return Base64.encodeBase64String(bytes);

}

public static byte[] base64Decode(String base64Code) throws Exception{

return new BASE64Decoder().decodeBuffer(base64Code);

}

public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {

KeyGenerator kgen = KeyGenerator.getInstance("AES");

kgen.init(128);

Cipher cipher = Cipher.getInstance(ALGORITHMSTR);

cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));

return cipher.doFinal(content.getBytes("utf-8"));

}

public static String aesEncrypt(String content, String encryptKey) throws Exception {

return base64Encode(aesEncryptToBytes(content, encryptKey));

}

public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {

KeyGenerator kgen = KeyGenerator.getInstance("AES");

kgen.init(128);

Cipher cipher = Cipher.getInstance(ALGORITHMSTR);

cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));

byte[] decryptBytes = cipher.doFinal(encryptBytes);

return new String(decryptBytes);

}

public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {

return aesDecryptByBytes(base64Decode(encryptStr), decryptKey);

}

/**

* 测试

*

*/

public static void main(String[] args) throws Exception {

 

String content = "Test String么么哒"; //0gqIDaFNAAmwvv3tKsFOFf9P9m/6MWlmtB8SspgxqpWKYnELb/lXkyXm7P4sMf3e

System.out.println("加密前:" + content);

System.out.println("加密密钥和解密密钥:" + KEY);

String encrypt = aesEncrypt(content, KEY);

System.out.println(encrypt.length()+":加密后:" + encrypt);

String decrypt = aesDecrypt(encrypt, KEY);

System.out.println("解密后:" + decrypt);

}}

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java中常用的密码加密方法有MD5、SHA、AES等,下面分别介绍它们的使用方法。 MD5加密: MD5是一种不可逆的加密方式,将明文密码转换成一串固定长度的字符串,一般用于存储密码的加密。Java中可以通过java.security.MessageDigest类实现MD5加密。示例代码如下: ```java import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5Util { public static String md5(String password) { try { MessageDigest md5 = MessageDigest.getInstance("MD5"); byte[] bytes = md5.digest(password.getBytes()); StringBuilder stringBuilder = new StringBuilder(); for (byte b : bytes) { int temp = b & 0xff; String hexString = Integer.toHexString(temp); if (hexString.length() == 1) { stringBuilder.append("0").append(hexString); } else { stringBuilder.append(hexString); } } return stringBuilder.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return null; } public static void main(String[] args) { String password = "123456"; String encryptedPassword = md5(password); System.out.println(encryptedPassword); } } ``` SHA加密: SHA也是一种不可逆的加密方式,与MD5类似,但SHA更安全。Java中可以通过java.security.MessageDigest类实现SHA加密。示例代码如下: ```java import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class SHAUtil { public static String sha(String password) { try { MessageDigest sha = MessageDigest.getInstance("SHA"); byte[] bytes = sha.digest(password.getBytes()); StringBuilder stringBuilder = new StringBuilder(); for (byte b : bytes) { int temp = b & 0xff; String hexString = Integer.toHexString(temp); if (hexString.length() == 1) { stringBuilder.append("0").append(hexString); } else { stringBuilder.append(hexString); } } return stringBuilder.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return null; } public static void main(String[] args) { String password = "123456"; String encryptedPassword = sha(password); System.out.println(encryptedPassword); } } ``` AES加密: AES是一种对称加密方式,即加密和解密使用相同的密钥。Java中可以通过javax.crypto.Cipher类实现AES加密。示例代码如下: ```java import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Base64; public class AESUtil { private static final String AES = "AES"; public static String encrypt(String content, String password) { try { KeyGenerator keyGenerator = KeyGenerator.getInstance(AES); SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); secureRandom.setSeed(password.getBytes()); keyGenerator.init(128, secureRandom); SecretKey secretKey = keyGenerator.generateKey(); byte[] enCodeFormat = secretKey.getEncoded(); SecretKeySpec key = new SecretKeySpec(enCodeFormat, AES); Cipher cipher = Cipher.getInstance(AES);// 创建密码器 byte[] byteContent = content.getBytes("utf-8"); cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化 byte[] result = cipher.doFinal(byteContent); return Base64.getEncoder().encodeToString(result);// 加密 } catch (Exception e) { e.printStackTrace(); } return null; } public static String decrypt(String content, String password) { try { KeyGenerator keyGenerator = KeyGenerator.getInstance(AES); SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); secureRandom.setSeed(password.getBytes()); keyGenerator.init(128, secureRandom); SecretKey secretKey = keyGenerator.generateKey(); byte[] enCodeFormat = secretKey.getEncoded(); SecretKeySpec key = new SecretKeySpec(enCodeFormat, AES); Cipher cipher = Cipher.getInstance(AES);// 创建密码器 cipher.init(Cipher.DECRYPT_MODE, key);// 初始化 byte[] result = cipher.doFinal(Base64.getDecoder().decode(content)); return new String(result, "utf-8"); } catch (Exception e) { e.printStackTrace(); } return null; } public static void main(String[] args) { String content = "123456"; String password = "password"; String encryptedContent = encrypt(content, password); System.out.println("加密后:" + encryptedContent); String decryptedContent = decrypt(encryptedContent, password); System.out.println("解密后:" + decryptedContent); } } ``` Spring Boot中可以使用Spring Security提供的PasswordEncoder接口来实现密码加密和解密。示例代码如下: ```java import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; public class PasswordUtil { public static String encode(String password) { PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); return passwordEncoder.encode(password); } public static boolean match(String password, String encodedPassword) { PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); return passwordEncoder.matches(password, encodedPassword); } public static void main(String[] args) { String password = "123456"; String encodedPassword = encode(password); System.out.println("加密后:" + encodedPassword); boolean match = match(password, encodedPassword); System.out.println("匹配结果:" + match); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值