SSM实现mysql数据库账号密码密文登录功能

 更新时间:2019年08月09日 10:20:09   作者:zsq_fengchen  
这篇文章主要介绍了SSM实现mysql数据库账号密码密文登录功能,本文分为三步给大家介绍的非常详细,具有一定的参考借鉴价值 ,需要的朋友可以参考下

引言

      咱们公司从事的是信息安全涉密应用的一些项目研发一共有分为三步,相比较于一般公司和一般的项目,对于信息安全要求更加严格,领导要求数据量和用户的用户名及密码信息都必需是要密文配置和存储的,这就涉及到jdbc.properties文件中的数据库的用户名和密码也是一样的,需要配置问密文,在连接的时候再加载解密为明文进行数据库的连接操作,以下就是实现过程,一共有分为三步。

一、创建DESUtil类

提供自定义密钥,加密解密的方法。

package com.hzdy.DCAD.common.util;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import java.security.Key;
import java.security.SecureRandom;
/**
 * Created by Wongy on 2019/8/8.
 */
public class DESUtil {
  private static Key key;
  //自己的密钥
  private static String KEY_STR = "mykey";
  static {
    try {
      KeyGenerator generator = KeyGenerator.getInstance("DES");
      SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
      secureRandom.setSeed(KEY_STR.getBytes());
      generator.init(secureRandom);
      key = generator.generateKey();
      generator = null;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
  /**
   * 对字符串进行加密,返回BASE64的加密字符串
   *
   * @param str
   * @return
   * @see [类、类#方法、类#成员]
   */
  public static String getEncryptString(String str) {
    BASE64Encoder base64Encoder = new BASE64Encoder();
    try {
      byte[] strBytes = str.getBytes("UTF-8");
      Cipher cipher = Cipher.getInstance("DES");
      cipher.init(Cipher.ENCRYPT_MODE, key);
      byte[] encryptStrBytes = cipher.doFinal(strBytes);
      return base64Encoder.encode(encryptStrBytes);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
  /**
   * 对BASE64加密字符串进行解密
   *
   */
  public static String getDecryptString(String str) {
    BASE64Decoder base64Decoder = new BASE64Decoder();
    try {
      byte[] strBytes = base64Decoder.decodeBuffer(str);
      Cipher cipher = Cipher.getInstance("DES");
      cipher.init(Cipher.DECRYPT_MODE, key);
      byte[] encryptStrBytes = cipher.doFinal(strBytes);
      return new String(encryptStrBytes, "UTF-8");
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
  public static void main(String[] args) {
    String name = "dbuser";
    String password = "waction2016";
    String encryname = getEncryptString(name);
    String encrypassword = getEncryptString(password);
    System.out.println("encryname : " + encryname);
    System.out.println("encrypassword : " + encrypassword);
    System.out.println("name : " + getDecryptString(encryname));
    System.out.println("password : " + getDecryptString(encrypassword));
  }
}

二、 创建EncryptPropertyPlaceholderConfigurer类

建立与配置文件的关联。

package com.hzdy.DCAD.common.util;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
public class EncryptPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
  //属性需与配置文件的KEY保持一直
  private String[] encryptPropNames = {"jdbc.username", "jdbc.password"};
  @Override
  protected String convertProperty(String propertyName, String propertyValue) {
    //如果在加密属性名单中发现该属性 
    if (isEncryptProp(propertyName)) {
      String decryptValue = DESUtil.getDecryptString(propertyValue);
      System.out.println(decryptValue);
      return decryptValue;
    } else {
      return propertyValue;
    }
  }
  private boolean isEncryptProp(String propertyName) {
    for (String encryptName : encryptPropNames) {
      if (encryptName.equals(propertyName)) {
        return true;
      }
    }
    return false;
  }
}

三、 修改配置文件 jdbc.properties

#加密配置之前
#jdbc.driver=com.mysql.jdbc.Driver
#jdbc.user=root
#jdbc.password=root
#jdbc.url=jdbc:mysql://localhost:3306/bookstore
#加密配置之后
jdbc.driver=com.mysql.jdbc.Driver
jdbc.user=Ov4j7fKiCzY=
jdbc.password=Ov4j7fKiCzY=
jdbc.url=jdbc:mysql://localhost:3306/bookstore

四、 修改spring-content.xml配置文件

将spring-context中的
 <context:property-placeholder location="classpath:.properties" />
 修改为
 <bean class="com.hzdy.DCAD.common.util.EncryptPropertyPlaceholderConfigurer"p:locations="classpath:*.properties"/>
 //注意只能存在一个读取配置文件的bean,否则系统只会读取最前面的

   注意:如果发现配置密文的usernamepassword可以加载并解密成功,但是最后连接的时候还是以密文连接并报错,这可能涉及到内存预加载的问题,项目一启动,程序会加密密文的用户名和密码,就算最后解密成功了,最后连接数据库读取的却还是密文,这时候我们可以自己重写连接池的方法,让spring-content.xml加载重写的连接池方法,并在连接的时候再提前进行解密。

package com.thinkgem.jeesite.common.encrypt;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.security.auth.callback.PasswordCallback;
import com.alibaba.druid.util.DruidPasswordCallback;
/**
 */
@SuppressWarnings("serial")
public class DruidDataSource extends com.alibaba.druid.pool.DruidDataSource {
  public PhysicalConnectionInfo createPhysicalConnection() throws SQLException {
    String url = this.getUrl();
    Properties connectProperties = getConnectProperties();
    String user;
    if (getUserCallback() != null) {
      user = getUserCallback().getName();
    } else {
      user = getUsername();
    }
    //DES解密
    user = DESUtils.getDecryptString(user);
    String password = DESUtils.getDecryptString(getPassword());
    PasswordCallback passwordCallback = getPasswordCallback();
    if (passwordCallback != null) {
      if (passwordCallback instanceof DruidPasswordCallback) {
        DruidPasswordCallback druidPasswordCallback = (DruidPasswordCallback) passwordCallback;
        druidPasswordCallback.setUrl(url);
        druidPasswordCallback.setProperties(connectProperties);
      }
      char[] chars = passwordCallback.getPassword();
      if (chars != null) {
        password = new String(chars);
      }
    }
    Properties physicalConnectProperties = new Properties();
    if (connectProperties != null) {
      physicalConnectProperties.putAll(connectProperties);
    }
    if (user != null && user.length() != 0) {
      physicalConnectProperties.put("user", user);
    }
    if (password != null && password.length() != 0) {
      physicalConnectProperties.put("password", password);
    }
    Connection conn;
    long connectStartNanos = System.nanoTime();
    long connectedNanos, initedNanos, validatedNanos;
    try {
      conn = createPhysicalConnection(url, physicalConnectProperties);
      connectedNanos = System.nanoTime();
      if (conn == null) {
        throw new SQLException("connect error, url " + url + ", driverClass " + this.driverClass);
      }
      initPhysicalConnection(conn);
      initedNanos = System.nanoTime();
      validateConnection(conn);
      validatedNanos = System.nanoTime();
      setCreateError(null);
    } catch (SQLException ex) {
      setCreateError(ex);
      throw ex;
    } catch (RuntimeException ex) {
      setCreateError(ex);
      throw ex;
    } catch (Error ex) {
      createErrorCount.incrementAndGet();
      throw ex;
    } finally {
      long nano = System.nanoTime() - connectStartNanos;
      createTimespan += nano;
    }
    return new PhysicalConnectionInfo(conn, connectStartNanos, connectedNanos, initedNanos, validatedNanos);
  }
}

修改spring-content.xml文件的数据库连接数配置

#修改之前
<!-- <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> -->
#修改之后
<bean id="dataSource"class="com.thinkgem.jeesite.common.encrypt.DruidDataSource" 
    init-method="init" destroy-method="close">
    <!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
    <property name="driverClassName" value="${jdbc.driver}" />
    <!-- 基本属性 url、user、password -->
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />

  </bean>

至此,数据库密文配置连接就完成了!

总结

以上所述是小编给大家介绍的SSM实现mysql数据库账号密码密文登录功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

相关文章

  • mysql limit 分页的用法及注意要点

    mysql limit 分页的用法及注意要点

    limit在mysql语句中使用的频率非常高,一般分页查询都会使用到limit语句,本文章向码农们介绍mysql limit 分页的用法与注意事项,需要的朋友可以参考下
    2016-12-12
  • MYSQL日志的正确删除方法详解

    MYSQL日志的正确删除方法详解

    这篇文章主要介绍了MYSQL日志的正确删除方法,详细分析了MySQL日志删除的步骤与相关注意事项,需要的朋友可以参考下
    2016-04-04
  • Dbeaver连接MySQL数据库及错误Connection refusedconnect处理方法

    Dbeaver连接MySQL数据库及错误Connection refusedconnect处理方法

    这篇文章主要介绍了dbeaver连接MySQL数据库及错误Connection refusedconnect处理方法,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • mysql如何设置不区分大小写

    mysql如何设置不区分大小写

    在本篇文章里小编给大家整理了关于mysql设置不区分大小写的方法,需要的朋友们跟着学习下。
    2020-06-06
  • MySQL千万表归档的项目实践

    MySQL千万表归档的项目实践

    本文主要介绍了MySQL千万表归档的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-02-02
  • mysql+mybatis实现存储过程+事务 + 多并发流水号获取

    mysql+mybatis实现存储过程+事务 + 多并发流水号获取

    这篇文章主要介绍了mysql+mybatis+存储过程+事务 + 多并发流水号获取,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12
  • mysql之跨库关联查询(dblink)问题

    mysql之跨库关联查询(dblink)问题

    这篇文章主要介绍了mysql之跨库关联查询(dblink)问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • 浅谈MySQL使用笛卡尔积原理进行多表查询

    浅谈MySQL使用笛卡尔积原理进行多表查询

    这篇文章主要介绍了浅谈MySQL使用笛卡尔积原理进行多表查询, 文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • mysql之数据库常用脚本总结

    mysql之数据库常用脚本总结

    这篇文章主要介绍了mysql之数据库常用脚本总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • mysql创建表添加字段注释的实现方法

    mysql创建表添加字段注释的实现方法

    这篇文章主要介绍了mysql创建表添加字段注释的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03

最新评论