最近没有及时写文章,把最近处理的几个问题集中了一下写出来。这篇文章是关于如何处理spring项目中引入数据库连接等

使用的用户名和密码的明文进行加密。防止被他人窃取利用。

我们选择的加密方式为DES加密解密方案。直接上代码:

1. 首先要编写一个DES加密解密工具。

package com.nc.jdbc;

import com.nc.utils.Base64;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException; /**
* Created by mazhqc on 2017/8/15.
*/
public class DESEncry
{
/** 安全密钥 */
private String keyData = "ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstwxyz0123456789-_."; /**
* 功能:构造
*
* @author 马振全
* @date 2017-08-15
*/
public DESEncry() {
} /**
* 功能:构造
*
* @author 马振全
* @date 2017-08-15
* @param keyData
* key
*/
public DESEncry(String key) {
this.keyData = key;
} /**
* 功能:加密 (UTF-8)
*
* @author 马振全
* @date 2017-08-15
* @param source
* 源字符串
* @param charSet
* 编码
* @return String
* @throws UnsupportedEncodingException
* 编码异常
*/
public String encrypt(String source) throws UnsupportedEncodingException {
return encrypt(source, "UTF-8");
} /**
*
* 功能:解密 (UTF-8)
*
* @author 马振全
* @date 2017-08-15
* @param encryptedData
* 被加密后的字符串
* @return String
* @throws UnsupportedEncodingException
* 编码异常
*/
public String decrypt(String encryptedData)
throws UnsupportedEncodingException {
return decrypt(encryptedData, "UTF-8");
} /**
* 功能:加密
*
* @author 马振全
* @date 2017-08-15
* @param source
* 源字符串
* @param charSet
* 编码
* @return String
* @throws UnsupportedEncodingException
* 编码异常
*/
public String encrypt(String source, String charSet)
throws UnsupportedEncodingException {
String encrypt = null;
byte[] ret = encrypt(source.getBytes(charSet));
encrypt = new String(Base64.encode(ret));
return encrypt;
} /**
*
* 功能:解密
*
* @author 马振全
* @date 2017-08-15
* @param encryptedData
* 被加密后的字符串
* @param charSet
* 编码
* @return String
* @throws UnsupportedEncodingException
* 编码异常
*/
public String decrypt(String encryptedData, String charSet)
throws UnsupportedEncodingException {
String descryptedData = null;
byte[] ret = descrypt(Base64.decode(encryptedData));
descryptedData = new String(ret, charSet);
return descryptedData;
} /**
* 加密数据 用生成的密钥加密原始数据
*
* @param primaryData
* 原始数据
* @return byte[]
* @author 马振全
* @date 2017-08-15
*/
private byte[] encrypt(byte[] primaryData) { /** 取得安全密钥 */
byte rawKeyData[] = getKey(); /** DES算法要求有一个可信任的随机数源 */
SecureRandom sr = new SecureRandom(); /** 使用原始密钥数据创建DESKeySpec对象 */
DESKeySpec dks = null;
try {
dks = new DESKeySpec(keyData.getBytes());
} catch (InvalidKeyException e) {
e.printStackTrace();
} /** 创建一个密钥工厂 */
SecretKeyFactory keyFactory = null;
try {
keyFactory = SecretKeyFactory.getInstance("DES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} /** 用密钥工厂把DESKeySpec转换成一个SecretKey对象 */
SecretKey key = null;
try {
key = keyFactory.generateSecret(dks);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} /** Cipher对象实际完成加密操作 */
Cipher cipher = null;
try {
cipher = Cipher.getInstance("DES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} /** 用密钥初始化Cipher对象 */
try {
cipher.init(Cipher.ENCRYPT_MODE, key, sr);
} catch (InvalidKeyException e) {
e.printStackTrace();
} /** 正式执行加密操作 */
byte encryptedData[] = null;
try {
encryptedData = cipher.doFinal(primaryData);
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} /** 返回加密数据 */
return encryptedData;
} /**
* 用密钥解密数据
*
* @param encryptedData
* 加密后的数据
* @return byte[]
* @author 马振全
* @date 2017-08-15
*/
private byte[] descrypt(byte[] encryptedData) { /** DES算法要求有一个可信任的随机数源 */
SecureRandom sr = new SecureRandom(); /** 取得安全密钥 */
byte rawKeyData[] = getKey(); /** 使用原始密钥数据创建DESKeySpec对象 */
DESKeySpec dks = null;
try {
dks = new DESKeySpec(keyData.getBytes());
} catch (InvalidKeyException e) {
e.printStackTrace();
} /** 创建一个密钥工厂 */
SecretKeyFactory keyFactory = null;
try {
keyFactory = SecretKeyFactory.getInstance("DES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} /** 用密钥工厂把DESKeySpec转换成一个SecretKey对象 */
SecretKey key = null;
try {
key = keyFactory.generateSecret(dks);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} /** Cipher对象实际完成加密操作 */
Cipher cipher = null;
try {
cipher = Cipher.getInstance("DES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} /** 用密钥初始化Cipher对象 */
try {
cipher.init(Cipher.DECRYPT_MODE, key, sr);
} catch (InvalidKeyException e) {
e.printStackTrace();
} /** 正式执行解密操作 */
byte decryptedData[] = null;
try {
decryptedData = cipher.doFinal(encryptedData);
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} return decryptedData;
} /**
* 取得安全密钥 此方法作废,因为每次key生成都不一样导致解密加密用的密钥都不一样, 从而导致Given final block not
* properly padded错误.
*
* @return byte数组
* @author 马振全
* @date 2017-08-15
*/
private byte[] getKey() { /** DES算法要求有一个可信任的随机数源 */
SecureRandom sr = new SecureRandom(); /** 为我们选择的DES算法生成一个密钥生成器对象 */
KeyGenerator kg = null;
try {
kg = KeyGenerator.getInstance("DES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
kg.init(sr); /** 生成密钥工具类 */
SecretKey key = kg.generateKey(); /** 生成密钥byte数组 */
byte rawKeyData[] = key.getEncoded(); return rawKeyData;
} }

2. 用到了一个Base64的工具代码如下:

package com.nc.utils;

/**
* Created by mazhqc on 2016/9/22.
*/
public final class Base64 { static private final int BASELENGTH = 128;
static private final int LOOKUPLENGTH = 64;
static private final int TWENTYFOURBITGROUP = 24;
static private final int EIGHTBIT = 8;
static private final int SIXTEENBIT = 16;
static private final int FOURBYTE = 4;
static private final int SIGN = -128;
static private final char PAD = '=';
static private final boolean fDebug = false;
static final private byte[] base64Alphabet = new byte[BASELENGTH];
static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH]; static {
for (int i = 0; i < BASELENGTH; ++i) {
base64Alphabet[i] = -1;
}
for (int i = 'Z'; i >= 'A'; i--) {
base64Alphabet[i] = (byte) (i - 'A');
}
for (int i = 'z'; i >= 'a'; i--) {
base64Alphabet[i] = (byte) (i - 'a' + 26);
} for (int i = '9'; i >= '0'; i--) {
base64Alphabet[i] = (byte) (i - '0' + 52);
} base64Alphabet['+'] = 62;
base64Alphabet['/'] = 63; for (int i = 0; i <= 25; i++) {
lookUpBase64Alphabet[i] = (char) ('A' + i);
} for (int i = 26, j = 0; i <= 51; i++, j++) {
lookUpBase64Alphabet[i] = (char) ('a' + j);
} for (int i = 52, j = 0; i <= 61; i++, j++) {
lookUpBase64Alphabet[i] = (char) ('0' + j);
}
lookUpBase64Alphabet[62] = (char) '+';
lookUpBase64Alphabet[63] = (char) '/'; } private static boolean isWhiteSpace(char octect) {
return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
} private static boolean isPad(char octect) {
return (octect == PAD);
} private static boolean isData(char octect) {
return (octect < BASELENGTH && base64Alphabet[octect] != -1);
} /**
* Encodes hex octects into Base64
*
* @param binaryData Array containing binaryData
* @return Encoded Base64 array
*/
public static String encode(byte[] binaryData) { if (binaryData == null) {
return null;
} int lengthDataBits = binaryData.length * EIGHTBIT;
if (lengthDataBits == 0) {
return "";
} int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
char encodedData[] = null; encodedData = new char[numberQuartet * 4]; byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; int encodedIndex = 0;
int dataIndex = 0;
if (fDebug) {
System.out.println("number of triplets = " + numberTriplets);
} for (int i = 0; i < numberTriplets; i++) {
b1 = binaryData[dataIndex++];
b2 = binaryData[dataIndex++];
b3 = binaryData[dataIndex++]; if (fDebug) {
System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3);
} l = (byte) (b2 & 0x0f);
k = (byte) (b1 & 0x03); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc); if (fDebug) {
System.out.println("val2 = " + val2);
System.out.println("k4 = " + (k << 4));
System.out.println("vak = " + (val2 | (k << 4)));
} encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
} // form integral number of 6-bit groups
if (fewerThan24bits == EIGHTBIT) {
b1 = binaryData[dataIndex];
k = (byte) (b1 & 0x03);
if (fDebug) {
System.out.println("b1=" + b1);
System.out.println("b1<<2 = " + (b1 >> 2));
}
byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
encodedData[encodedIndex++] = PAD;
encodedData[encodedIndex++] = PAD;
} else if (fewerThan24bits == SIXTEENBIT) {
b1 = binaryData[dataIndex];
b2 = binaryData[dataIndex + 1];
l = (byte) (b2 & 0x0f);
k = (byte) (b1 & 0x03); byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
encodedData[encodedIndex++] = PAD;
} return new String(encodedData);
} /**
* Decodes Base64 data into octects
*
* @param encoded string containing Base64 data
* @return Array containind decoded data.
*/
public static byte[] decode(String encoded) { if (encoded == null) {
return null;
} char[] base64Data = encoded.toCharArray();
// remove white spaces
int len = removeWhiteSpace(base64Data); if (len % FOURBYTE != 0) {
return null;//should be divisible by four
} int numberQuadruple = (len / FOURBYTE); if (numberQuadruple == 0) {
return new byte[0];
} byte decodedData[] = null;
byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
char d1 = 0, d2 = 0, d3 = 0, d4 = 0; int i = 0;
int encodedIndex = 0;
int dataIndex = 0;
decodedData = new byte[(numberQuadruple) * 3]; for (; i < numberQuadruple - 1; i++) { if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
|| !isData((d3 = base64Data[dataIndex++]))
|| !isData((d4 = base64Data[dataIndex++]))) {
return null;
}//if found "no data" just return null b1 = base64Alphabet[d1];
b2 = base64Alphabet[d2];
b3 = base64Alphabet[d3];
b4 = base64Alphabet[d4]; decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
} if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) {
return null;//if found "no data" just return null
} b1 = base64Alphabet[d1];
b2 = base64Alphabet[d2]; d3 = base64Data[dataIndex++];
d4 = base64Data[dataIndex++];
if (!isData((d3)) || !isData((d4))) {//Check if they are PAD characters
if (isPad(d3) && isPad(d4)) {
if ((b2 & 0xf) != 0)//last 4 bits should be zero
{
return null;
}
byte[] tmp = new byte[i * 3 + 1];
System.arraycopy(decodedData, 0, tmp, 0, i * 3);
tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
return tmp;
} else if (!isPad(d3) && isPad(d4)) {
b3 = base64Alphabet[d3];
if ((b3 & 0x3) != 0)//last 2 bits should be zero
{
return null;
}
byte[] tmp = new byte[i * 3 + 2];
System.arraycopy(decodedData, 0, tmp, 0, i * 3);
tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
return tmp;
} else {
return null;
}
} else { //No PAD e.g 3cQl
b3 = base64Alphabet[d3];
b4 = base64Alphabet[d4];
decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); } return decodedData;
} /**
* remove WhiteSpace from MIME containing encoded Base64 data.
*
* @param data the byte array of base64 data (with WS)
* @return the new length
*/
private static int removeWhiteSpace(char[] data) {
if (data == null) {
return 0;
} // count characters that's not whitespace
int newSize = 0;
int len = data.length;
for (int i = 0; i < len; i++) {
if (!isWhiteSpace(data[i])) {
data[newSize++] = data[i];
}
}
return newSize;
}
}

3. 我们引入的jdbc.properties的时候如下那么我们可以在这里进行加密处理。

 <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>

  jdbc.properties中的内容如下:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mzq?userUnicode=true&characterEncoding=utf8&allowMultiQueries=true
username=root
password=123456

4. 写一个类 EncryptablePropertyPlaceholderConfigurer继承PropertyPlaceholderConfigurer代码如下:

package com.nc.jdbc;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; import java.util.Properties; /**
* Created by mazhqc on 2017/8/15.
*/
public class EncryptablePropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer { protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
throws BeansException {
try {
DESEncry desEncry = new DESEncry();
String username = props.getProperty("username");
if (username != null) {
props.setProperty("username", String.valueOf(desEncry.decrypt(username)));
} String password = props.getProperty("password");
if (password != null) {
props.setProperty("password", String.valueOf(desEncry.decrypt(password)));
}
super.processProperties(beanFactory, props);
} catch (Exception e) {
e.printStackTrace();
throw new BeanInitializationException(e.getMessage());
}
}
}

5. 把jdbc文件引入的地方改为自己新写的实现类和修改jdbc文件中用户名和密码为加密后的即可。

  <bean id="propertyConfigurer" class="com.nc.jdbc.EncryptablePropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>

大功告成。

  如果觉得有疑问或者对你有帮助 欢迎评论。

  作者:森林木马

如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意

转载文章之后必须在 文章页面明显位置给出作者和原文连接否则保留追究法律责任的权利。

 

将jdbc连接明文密码加密方案的更多相关文章

  1. Spring Boot (四): Druid 连接池密码加密与监控

    在上一篇文章<Spring Boot (三): ORM 框架 JPA 与连接池 Hikari> 我们介绍了 JPA 与连接池 Hikari 的整合使用,在国内使用比较多的连接池还有一个是阿 ...

  2. SSM项目的数据库密码加密方案

    项目主要采用:SpringMVC4.3.2.RELEASE +Spring4.3.2.RELEASE + Maven 3.3.3 + druid 1.0.29 + Mybatis 3.2.8 + My ...

  3. 基于RSA的WEB前端密码加密方案

    受制于WEB页面源码的暴露,因此传统的对称加密方案以及加密密钥都将暴露在JS文件中,同样可以被解密. 目前比较好的解决方案是WEB页面全程或用户登录等关键环节使用HTTPS进行传输. 另外一种解决方案 ...

  4. Mysql的下载,安装,远程连接,密码加密规则修改。

    第一次接触mysql,,很多地方不懂,出了很多问题.本来应该在Linux系统中安装mysql的,但是奈何各种电脑限制,所以在公司电脑的Windows service R2 系统上装了mysql数据库. ...

  5. 如果你的application.properties中还存在明文密码----加密Spring Boot中的application.properties

    1 概述 什么?都2020年了还在Spring Boot的配置文件中写明文密码? 虽然是小项目,明文也没人看. 明文简单快捷方便啊!!! 你看直接用户名root密码123456多么简单!!! ... ...

  6. Spring Boot 配置文件密码加密两种方案

    Spring Boot 配置文件密码加密两种方案 jasypt 加解密 jasypt 是一个简单易用的加解密Java库,可以快速集成到 Spring 项目中.可以快速集成到 Spring Boot 项 ...

  7. Apach Shiro MD5密码加密过程(明文生成密码过程)详细解析

    前言: 最近再项目当中使用的ApachShiro安全框架,对于权限和服务器资源的保护都有一个很好的管理.前期主要参考的文章有 项目中设计密码的加盐处理以及二次加密问题,跟着断点 一步步揭开Apach ...

  8. 使用 SSL 加密的 JDBC 连接 SAP HANA 数据库

    近期客户为满足安全要求,提了让业务应用使用 SSL 方式连接 SAP HANA 数据库的需求.本人查询 SAP官方文档 发现数据库支持 SSL 连接,有参数直接加到 JDBC 的 URL 后边就行了, ...

  9. 关于mysql8.0及以上版本连接navicat时候报错(密码加密方式需要修改)

    首先这个原因是因为MySQL版本的密码加密方式变了,要把它修改成以前的方式(因为,navicat不支持这种方式) 1:先进入mysql: mysql -uroot -p123456; 2:查询密码加密 ...

随机推荐

  1. JWT(JSON Web Token) 多网站的单点登录,放弃session

    多个网站之间的登录信息共享, 一种解决方案是基于cookie - session的登录认证方式,这种方式跨域比较复杂. 另一种替代方案是采用基于算法的认证方式, JWT(json web token) ...

  2. Linux实战案例(5)关闭Centos的防火墙

    1.检查防火墙的状态 [root@LxfN1 ~]# service iptables status表格:filterChain INPUT (policy ACCEPT)num target pro ...

  3. leetcode算法: Find Largest Value in Each Tree Row

    '''You need to find the largest value in each row of a binary tree.Example:Input: 1 / \ 3 2 / \ \ 5 ...

  4. Python/Django(CBV/FBV/ORM操作)

    Python/Django(CBV/FBV/ORM操作) CBV:url对应的类(模式) ##====================================CBV操作============ ...

  5. flask +gevent+nginx+Gunicorn+supervisor部署flask应用

    上篇   可以完美部署flask ,但是视乎在结合gevent+apscheduler 实现异步非阻塞后台和定时任务的时候视乎不是那么完美.请教了前辈,决定使用flask+gevent+nginx+g ...

  6. .net core 使用阿里云短信发送SMS

    阿里云官方的skd(aliyun-net-sdk-core,aliyun-net-sdk-dysmsapi)在dnc中发送短信会出错,nuget上的包貌似也一样不管用.直接改下sdk当然也可以,但就发 ...

  7. HTML5示例之WebSocket

    Web应用程序通常有一些耗时的操作,但有些操作耗时不是很长,一分钟之内能完成.如果采用后台任务队列去异步处理,这样的用户不能实时看到后台处理的情况.倘若用户触发操作后,Web页面能够实时看到后台处理的 ...

  8. Hibernate(十一):映射继承关系的三种方案

    背景: 在一些项目中,会采用集成的关系来定义数据库实体类,比如:人(Person)与学生(Student),学生来源与人,所以人的基本属性学生也拥有:但学生有的一些属性,人就不具有.人与学生之间很显然 ...

  9. vue-router动态路由 刷新页面 静态资源没有加载的原因

    在做项目的时候,发现刷新页面的时候,静态路由没有加载,度娘了一圈,终于解决了. vue-router使用history模式+使用嵌套路由: 访问路由和嵌套路由页面,显示正常,但是刷新页面的时候,嵌套路 ...

  10. requests之一:HTTP请求 状态码

    1.请求方法主要有如下几种: Verb 描述 HEAD 只获取某个资源的头部信息,元数据.比如只想了解某个文件的大小,某个资源的修改日期等 GET 获取资源,一个或者多个 POST 创建资源 PATC ...