ApacheJames数据库存储用户信息的密码加密问题及解决方案,


目录
  • 项目场景
  • 1.将James的用户改为数据库存储
    • 1、修改存储方式
    • 3、添加依赖包
    • 4、创建用户表
  •  2.James密码是如何加密验证的
    • 3.总结

      项目场景

      Apache James邮件服务器使用数据库来存储用户信息的密码加密问题:

      • 将James的用户改为数据库存储
      • James密码是如何加密验证的

      1.将James的用户改为数据库存储

      1、修改存储方式

      找到james-2.3.2\apps\james\SAR-INF\config.xml

      找到<users-store>标签,注释掉原来文件存储的方式,改为数据库的方式

      maildb:是后面配置的数据源名称

      mail_users:是存储用户信息的表名

      <users-store>
        <!-- 注释掉原来文件存储的方式 -->
        <!--
        <repository name="LocalUsers" class="org.apache.james.userrepository.UsersFileRepository">
      	 <destination URL="file://var/users/"/>
        </repository>
      	 -->
        <!-- 改为数据库的方式 -->
        <repository name="LocalUsers" class="org.apache.james.userrepository.JamesUsersJdbcRepository" destinationURL="db://maildb/mail_users">
      	 <sqlFile>file://conf/sqlResources.xml</sqlFile>
        </repository>
      </users-store>

       2.、配置数据库信息

      找到<data-source>标签,根据具体数据库类型进行配置,下面已国产达梦数据库为例

      maildb:数据源名称 

      <data-source name="maildb" class="org.apache.james.util.dbcp.JdbcDataSource">
      	<driver>dm.jdbc.driver.DmDriver</driver>
      	<dburl>jdbc:dm://127.0.0.1:5236/test_mail</dburl>
      		<user>test</user>
      	<password>test123</password>
      	<max>50</max>
      </data-source>

      3、添加依赖包

      因为我用的是达梦数据库,james里面没有这个数据库的依赖包,所以需要额外添加,如果是mysql、oracle常用的数据库就不需要再额外添加,因为james已经支持。

      找到james-2.3.2\lib,然后把需要的依赖包放进去

      4、创建用户表

      正常情况下会自动创建,sql语句在james-2.3.2\apps\james\conf\sqlResources.xml

      如果不会自动创建,那么自己把sql语句复制出来执行

      CREATE TABLE "MAIL_USERS"
      (
      	"USERNAME" VARCHAR2(64) NOT NULL,
      	"PWDHASH" VARCHAR2(50),
      	"PWDALGORITHM" VARCHAR2(20),
      	"USEFORWARDING" NUMBER(1,0),
      	"FORWARDDESTINATION" VARCHAR2(255),
      	"USEALIAS" NUMBER(1,0),
      	"ALIAS" VARCHAR2(255),
      	PRIMARY KEY("USERNAME")
      );
      COMMENT ON TABLE "MAIL_USERS" IS 'James邮件用户';
      COMMENT ON COLUMN "MAIL_USERS"."PWDALGORITHM" IS '加密方式,默认SHA';
      COMMENT ON COLUMN "MAIL_USERS"."PWDHASH" IS '加密后的密码';
      COMMENT ON COLUMN "MAIL_USERS"."USERNAME" IS '邮箱帐号';

       2.James密码是如何加密验证的

              当你通过telnet添加新用户时,比如add user test 123456,你可以查看数据库中的记录,username字段是test,pwdhash是加密后的密码,pwdalgorithm字段是“SHA”,显然用的是SHA加密方式。

              让我们看下james源码是如何实现的,网上找到apache-james-2.3.2-src.zip源码文件,版本根据自己的来,然后用idea打开。

              我们找到org.apache.james.userrepository.DefaultUser类

              第一个方法verifyPassword()是用来做密码认证,传入的参数是明文密码,通过DigestUtil.digestString()方法,转换成密文密码,然后与数据库中密码作比较,返回比较结果。请注意这里的DigestUtil.digestString()方法,在后面还在提到。

              第二个方法setPassword()是用于密码转换的,把明文转成密文,用的同样是DigestUtil.digestString()方法。

              让我们再看下 org.apache.james.security.DigestUtil类,我们可以看到digestString加密的方法。

              如果需要在自己的项目里去添加或修改用户的信息,这时候密码处理的逻辑肯定需要跟james一致,这时候我们把这个加密的方法拷贝用就行了 。

              创建个DigestUtil类,然后调用DigestUtil.digestString()来获得加密后的密码。

      package com.mail;
      import javax.mail.MessagingException;
      import javax.mail.internet.MimeUtility;
      import java.io.ByteArrayOutputStream;
      import java.io.IOException;
      import java.io.OutputStream;
      import java.security.MessageDigest;
      import java.security.NoSuchAlgorithmException;
      public class DigestUtil {
          public static String digestString(String pass, String algorithm )
                  throws NoSuchAlgorithmException  {
              MessageDigest md;
              ByteArrayOutputStream bos;
              try {
                  md = MessageDigest.getInstance(algorithm);
                  byte[] digest = md.digest(pass.getBytes("iso-8859-1"));
                  bos = new ByteArrayOutputStream();
                  OutputStream encodedStream = MimeUtility.encode(bos, "base64");
                  encodedStream.write(digest);
                  return bos.toString("iso-8859-1");
              } catch (IOException ioe) {
                  throw new RuntimeException("Fatal error: " + ioe);
              } catch (MessagingException me) {
                  throw new RuntimeException("Fatal error: " + me);
              }
          }
          private DigestUtil() {}
      }

              加密支持的算法有MD5、SHA、SHA-256等 ,如果你想知道支持哪些算法,可以通过下面的代码列出所有支持的算法:

      import java.security.Security;
      import java.security.Provider;
      import java.security.Provider.Service;
      public class ListAlgorithms {
          public static void main(String[] args) {
              for(Provider provider: Security.getProviders()) {
                  for(Service service: provider.getServices()) {
                      if ("MessageDigest".equals(service.getType())) {
                          System.out.println(service.getAlgorithm());
                      }
                  }
              }
          }
      }

      3.总结

              集成java mail直接用明文帐号密码连接就行了,因为james会自己去加密验证,其他软件通过pop3配置,密码也是用明文就行了。

              如果觉得这种连接方式不安全有两种解决方案:

      修改james源码,比较麻烦。密码在web端加密,传输到自己后台再解密,然后用解密后的密码连接james。
      import javax.mail.*;
      import javax.mail.internet.*;
      import java.util.*;
      public class SendEmail {
          public static void main(String[] args) {
              String host = "smtp.example.com"; // SMTP服务器地址
              String username = "your-username"; // 用户名
              String password = "your-password"; // 密码
              Properties props = new Properties();
              props.put("mail.smtp.host", host);
              props.put("mail.smtp.auth", "true");
              Session session = Session.getInstance(props, new Authenticator() {
                  @Override
                  protected PasswordAuthentication getPasswordAuthentication() {
                      return new PasswordAuthentication(username, password);
                  }
              });
              try {
                  Message message = new MimeMessage(session);
                  message.setFrom(new InternetAddress("from@example.com"));
                  message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("to@example.com"));
                  message.setSubject("Email Subject");
                  message.setText("Email Body");
                  Transport.send(message);
                  System.out.println("Email sent successfully");
              } catch (MessagingException e) {
                  throw new RuntimeException("Error sending email", e);
              }
          }
      }

      到此这篇关于Apache James数据库存储用户信息的密码加密问题的文章就介绍到这了,更多相关Apache James密码加密内容请搜索PHP之友以前的文章或继续浏览下面的相关文章希望大家以后多多支持PHP之友!

      您可能感兴趣的文章:
      • java利用Apache commons codec进行MD5加密,BASE64加密解密,执行系统命令
      • 让Apache 2支持.htaccess并实现目录加密的方法

      相关内容