Skip to content

用户管理 ​

1. 概述 ​

MwUserService 是 tio-mail-wing 项目中负责处理所有用户相关业务逻辑的核心服务层组件。它的主要职责包括用户身份认证和用户信息查询,为上层应用(如 IMAP 的 LOGIN 命令处理模块)提供稳定、安全的接口。


2. 服务层实现 (MwUserService.java) ​

2.1. 类定义与职责 ​

java
package com.tio.mail.wing.service;

import nexus.io.db.activerecord.Db;
import nexus.io.db.activerecord.Row;
import nexus.io.template.SqlTemplates;
import nexus.io.tio.utils.digest.Sha256Utils;

public class MwUserService {
  /**
   * 认证用户
   * @param username 用户名
   * @param password 密码
   * @return 是否成功
   */
  public Long authenticate(String username, String password) {
    String sql = "select id,password_hash from mw_user where username=? and deleted=0";
    Row row = Db.findFirst(sql, username);
    String user_password_hash = row.getString("password_hash");
    if (user_password_hash != null) {
      if (Sha256Utils.checkPassword(password, user_password_hash)) {
        return row.getLong("id");
      }
    }
    return null;

  }

  public boolean userExists(String username) {
    String sql = "select count(1) from mw_user where username=? and deleted=0";
    return Db.existsBySql(sql, username);
  }

  public boolean userExists(Long userId) {
    String sql = "select count(1) from mw_user where id=? and deleted=0";
    return Db.existsBySql(sql, userId);
  }

  public Long getUserIdByUsername(String username) {
    String sql = "select id from mw_user where username=? and deleted=0";
    return Db.queryLong(sql, username);
  }

  public Row getUserByUsername(String username) {
    return Db.findFirst(SqlTemplates.get("mailbox.user.findByUsername"), username);
  }
}

2.2. 核心方法详解 ​

2.2.1. 用户身份认证 (authenticate) ​

此方法是用户登录流程的核心,用于验证用户提供的用户名和密码是否正确。

方法签名:

java
public boolean authenticate(String username, String password)

功能描述: 根据传入的用户名和明文密码,与数据库中存储的哈希密码进行比对,以完成身份认证。

参数:

  • String username: 用户邮箱地址。
  • String password: 用户输入的明文密码。

返回值:

  • boolean: 如果用户名存在且密码匹配,返回 true;否则返回 false。

实现逻辑:

  1. 查询密码哈希: 构造 SQL 语句 select password_hash from mw_user where username=? and deleted=0,从 mw_user 表中查询指定用户的密码哈希值。deleted=0 条件确保了只对有效用户进行认证。
  2. 用户存在性检查: 使用 Db.queryStr() 执行查询。如果返回的 user_password_hash 不为 null,说明用户存在。
  3. 密码比对: 如果用户存在,则调用 Sha256Utils.checkPassword(password, user_password_hash) 方法。该方法会使用与存储时相同的算法(PBKDF2 或 bcrypt)和参数(盐、迭代次数)来哈希传入的明文密码,并与数据库中的哈希值进行安全比较。
  4. 返回结果: 如果用户不存在或密码比对失败,方法最终返回 false。

代码实现:

java
/**
 * 认证用户
 * @param username 用户名
 * @param password 密码
 * @return 是否成功
 */
public boolean authenticate(String username, String password) {
  String sql = "select password_hash from mw_user where username=? and deleted=0";
  String user_password_hash = Db.queryStr(sql,username);
  if(user_password_hash!=null) {
    // 调用密码工具类进行安全比对
    return Sha256Utils.checkPassword(password, user_password_hash);
  }
  return false;
}

2.2.2. 检查用户是否存在 (userExists) ​

一个辅助方法,用于快速判断一个指定的用户账户是否存在于系统中。

方法签名:

java
public boolean userExists(String username)

功能描述: 检查具有给定用户名的有效账户(未被逻辑删除)是否存在。

参数:

  • String username: 需要检查的用户邮箱地址。

返回值:

  • boolean: 如果用户存在,返回 true;否则返回 false。

实现逻辑:

  1. 构造 SQL: 使用 select count(1) from mw_user where username=? and deleted=0 查询语句。
  2. 高效查询: 调用框架提供的 Db.existsBySql() 方法。该方法通常比 query 后判断 count > 0 更高效,因为它可能在找到第一条匹配记录后就提前返回。

代码实现:

java
public boolean userExists(String username) {
  String sql = "select count(1) from mw_user where username=? and deleted=0";
  return Db.existsBySql(sql, username);
}

3. 集成测试 (MwUserServiceTest.java) ​

为了确保 MwUserService 的正确性和稳定性,我们编写了集成测试用例。这些测试用例在真实的应用上下文中运行,能够访问数据库,从而验证完整的业务流程。

3.1. 测试环境设置 ​

测试类利用 TioBootTest.runWith(MwAdminAppConfig.class) 来启动一个嵌入式的应用环境。这会加载 MwAdminAppConfig 中定义的配置,包括数据库连接池,使得测试代码能够像在真实应用中一样获取服务实例和访问数据库。

3.2. 测试用例详解 ​

3.2.1. 测试用户存在性 (testUserExists) ​

  • 测试目标: 验证 userExists 方法能否正确判断一个不存在的用户。
  • 测试场景: 查询一个未在数据库中初始化的用户 user3@tio.com。
  • 预期结果: 控制台输出 false。
java
@Test
public void testUserExists() {
  TioBootTest.runWith(MwAdminAppConfig.class);
  boolean userExists = Aop.get(MwUserService.class).userExists("user3@tio.com");
  System.out.println(userExists);
}

3.2.2. 测试用户认证 (testAuthenticate) ​

  • 测试目标: 验证 authenticate 方法在密码错误时的行为。
  • 测试场景: 尝试使用正确的用户名 user1@tio.com 和一个明显错误的密码 00000000 进行认证。
  • 预期结果: 控制台输出 false。
java
@Test
public void testAuthenticate() {
  TioBootTest.runWith(MwAdminAppConfig.class);
  // 使用一个错误的密码进行测试
  boolean isAuthenticated = Aop.get(MwUserService.class).authenticate("user1@tio.com", "00000000");
  System.out.println(isAuthenticated);
}

通过以上服务实现和测试用例,我们为系统的用户管理模块奠定了坚实、可靠的基础。

MIT Licensed