跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

Spring Boot 项目用户模块设计:注册登录、权限管控与敏感数据加密

基于 Spring Boot 的用户模块设计方案,涵盖注册登录流程、权限管控及敏感数据加密技术。核心内容包括密码加盐哈希存储、手机号 AES 加密、MyBatis TypeHandler 自动处理、全局异常处理机制。登录功能采用 JWT 实现无状态认证,结合 Redis 缓存验证码。此外还实现了强制登录拦截器、管理员后台管理及用户列表展示等功能,为构建安全的用户系统提供完整后端架构参考。

萤火微光发布于 2026/3/29更新于 2026/10/22106 浏览
Spring Boot 项目用户模块设计:注册登录、权限管控与敏感数据加密

一、注册

1.1 敏感字段加密

用户注册时,密码和手机号等敏感信息需加密存储,避免明文泄露风险。

  • 密码加密:采用加盐哈希(SHA-256)方案,用户注册时生成随机盐值,将密码与盐拼接后进行哈希运算,最终存储哈希结果,确保不可逆。
  • 手机号加密:因业务可能需使用明文手机号(如发送短信),采用 AES 对称加密,存储加密后的结果,使用时解密。
  • 加密工具:引入国产 Java 工具类库 Hutool,封装加密解密方法,简化开发。

Hutool 官方文档:https://hutool.cn/ Maven 仓库地址:https://mvnrepository.com/artifact/cn.hutool

可引入以下依赖使用:

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.25</version>
</dependency>

1.2 用户注册

前后端交互接口

  • 请求:/register POST
{
  "name": "张三",
  "mail": "[email protected]",
  "phoneNumber": "13188888888",
  "password": "123456789",
  "identity": "ADMIN"

}
  • 响应:
{
  "code": 200,
  "data": {
    "userId": 22
  },
  "msg": ""
}

Controller 层接口设计

  • 接收注册参数,通过 @Validated 注解进行参数校验,调用 Service 层完成注册逻辑,返回注册结果。
  • 核心类:
    • UserRegisterParam:注册入参封装(姓名、邮箱、手机号、密码、身份),含 @NotBlank 等校验注解。
    • UserRegisterResult:注册出参封装(用户 ID)。
    • UserIdentityEnum:用户身份枚举(普通用户 NORMAL、管理员 ADMIN)。

控制层代码示例:

@RestController
public class UserController {
    private static final Logger logger = LoggerFactory.getLogger(UserController.class);

    @Autowired
    private UserService userService;

    @Autowired
    private VerificationCodeService verificationCodeService;

    /**
     * 注册
     * @param param
     * @return
     */
    @PostMapping("/register")
    public CommonResult<UserRegisterResult> userRegister(@Validated @RequestBody UserRegisterParam param) {
        // 日志打印
        logger.info("userRegister UserRegisterParam 用户注册:{}", JacksonUtil.writeValueAsString(param));
        // 调用 Service 层服务进行访问
        UserRegisterDTO userRegisterDTO = userService.register(param);
        return CommonResult.success(convertToUserRegisterResult(userRegisterDTO));
    }

    private UserRegisterResult convertToUserRegisterResult(UserRegisterDTO userRegisterDTO) {
        UserRegisterResult result = new UserRegisterResult();
        if (null == userRegisterDTO) {
            throw new ControllerException(ControllerErrorCodeConstants.REGISTER_ERROR);
        }
        result.setUserId(userRegisterDTO.getUserId());
        return result;
    }
}

使用 SpringBoot 中集成的 Validation 需要引入依赖:

<!-- spring-boot 2.3 及以上的版本只需要引入下面的依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Service 层接口设计

  • 接口与实现分离,定义 UserService 接口,UserServiceImpl 实现具体逻辑:
    1. 校验注册信息(邮箱格式、手机号格式、身份合法性、密码格式、邮箱/手机号唯一性)。
    2. 对密码和手机号进行加密处理。
    3. 调用 Dao 层将用户信息存入数据库。
    4. 返回用户 ID 封装结果。
  • 核心工具类:RegexUtil,封装邮箱、手机号、密码的格式校验正则表达式。

实现类代码示例:

@Slf4j
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private VerificationCodeService verificationCodeService;

    /**
     * 注册
     *
     * @param param
     * @return
     */
    @Override
    public UserRegisterDTO register(UserRegisterParam param) {
        // 校验用户信息
        checkRegisterInfo(param);
        // 加密数据
        UserDO userDO = new UserDO();
        userDO.setUserName(param.getName());
        userDO.setEmail(param.getMail());
        userDO.setPhoneNumber(newEncrypt(param.getPhoneNumber()));
        userDO.setIdentity(param.getIdentity());
        if (StringUtils.hasLength(param.getPassword())) {
            userDO.setPassword(DigestUtil.sha256Hex(param.getPassword()));
        }
        // 保存用户数据
        userMapper.insert(userDO);
        // 构造返回 UserRegisterDTO
        UserRegisterDTO userRegisterDTO = new UserRegisterDTO();
        userRegisterDTO.setUserId(userDO.getId());
        return userRegisterDTO;
    }

    private void checkRegisterInfo(UserRegisterParam param) {
        if (null == param) {
            throw new ServiceException(ServiceErrorCodeConstants.REGISTER_INFO_IS_EMPTY);
        }
        // 校验邮箱格式 [email protected]
        if (!RegexUtil.checkMail(param.getMail())) {
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_ERROR);
        }
        // 校验手机号格式
        if (!RegexUtil.checkMobile(param.getPhoneNumber())) {
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }
        // 校验身份信息
        if (null == UserIdentityEnum.forName(param.getIdentity())) {
            throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
        }
        // 校验密码(管理员必填)
        if (param.getIdentity().equalsIgnoreCase(UserIdentityEnum.ADMIN.name()) && !StringUtils.hasLength(param.getPassword())) {
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_IS_EMPTY);
        }
        // 校验密码格式 至少 6 位
        if (StringUtils.hasLength(param.getPassword()) && !RegexUtil.checkPassword(param.getPassword())) {
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_ERROR);
        }
        // 校验邮箱唯一
        if (checkMailUsed(param.getMail())) {
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_USED);
        }
        // 校验手机号唯一
        if (checkPhoneNumberUsed(param.getPhoneNumber())) {
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_USED);
        }
    }

    /**
     * 检验手机号是否被使用
     * @param phoneNumber
     * @return
     */
    private boolean checkPhoneNumberUsed(String phoneNumber) {
        int count = userMapper.countByPhone(newEncrypt(phoneNumber));
        return count > 0;
    }

    /**
     * 校验邮箱是否被使用
     * @param mail
     * @return
     */
    private boolean checkMailUsed(String mail) {
        int count = userMapper.countByMail(mail);
        return count > 0;
    }
}

接口分离设计的好处: 有助于创建更加灵活、可维护和可扩展的软件系统。抽象与具体实现分离:接口定义了一组操作的契约,而实现则提供了这些操作的具体行为。这种分离允许改变具体实现而不影响使用接口的客户端代码。支持多态性:接口允许通过共同的接口来引用不同的实现,这是多态性的基础,使得代码更加灵活和通用。提高代码的可读性和可理解性:接口提供了清晰的 API 视图,使得其他开发者能够更容易地理解和使用这些 API。安全性:接口可以隐藏实现细节,只暴露必要的操作,这有助于保护系统的内部状态和实现不被外部直接访问。遵循开闭原则:软件实体应当对扩展开放,对修改封闭。接口与实现的分离使得在不修改客户端代码的情况下扩展系统的功能。促进面向对象的设计:接口与实现的分离鼓励开发者进行面向对象的设计,考虑如何将系统分解为可重用和可组合的组件。


Dao 层接口设计

  • 使用 MyBatis 实现数据库交互,核心接口 UserMapper:
    • insert:插入用户信息,支持自动生成主键。
    • countByPhoneNumber:查询手机号绑定的用户数(校验唯一性)。
    • countByMail:查询邮箱绑定的用户数(校验唯一性)。
  • 核心类:UserDO,映射用户表,继承 BaseDO(含主键 id、创建时间 gmtCreate、更新时间 gmtModified)。

注册页面前端实现

  • 使用 jQuery Validate 插件校验表单字段(姓名、邮箱、手机号、密码必填,密码长度≥6)。
  • 表单验证通过后,通过 AJAX 发送 POST 请求到 /register 接口,携带用户注册信息。
  • 注册成功跳转登录页,失败提示错误信息。

1.3 TypeHandler

对手机号进行存储时,要先将手机号加密,如果要拿出使用时,还要进行一次解密操作。为简化手机号的自动加解密操作,使用 MyBatis 的 TypeHandler 实现字段处理。

TypeHandler:简单理解就是当处理特殊字段时,实现一些方法,让 mybatis 遇到这些特定字段可以自动运行处理。

  • Encrypt 类:标记需加解密的字段类型,封装待加密的字符串值。
  • EncryptTypeHandler 类:实现 BaseTypeHandler<Encrypt>,重写以下方法:
    • setNonNullParameter:设置参数时对手机号进行 AES 加密。
    • getNullableResult:查询结果时对手机号进行 AES 解密。
  • 配置:在 application.properties 中指定 TypeHandler 的包路径。

二、控制层通用异常处理

使用 @RestControllerAdvice + @ExceptionHandler 实现全局异常处理,统一响应格式。可以针对所有异常类型先进行通用处理后,再对特定异常类型进行不同的处理操作。

  • 捕获 Exception、ServiceException、ControllerException 三类异常。
  • 日志记录异常信息,返回 CommonResult 格式的错误响应,包含错误码和错误提示。

三、登录

3.1 发送验证码

采用阿里云短信服务发送验证码,支持短信登录方式。因为没用企业认证,只能使用其提供的一些特定模板,示例如下:

配置

  • 在 application.properties 中配置阿里云短信服务的 AccessKeyId、AccessKeySecret、签名名称。

核心工具类

  • SMSUtil:封装短信发送逻辑,通过阿里云 SDK 调用短信接口,处理发送结果。
  • CaptchaUtil:基于 Hutool 生成随机数字验证码。

CaptchaUtil 示例:

/**
 * 随机验证码生成工具
 */
public class CaptchaUtil {
    /**
     * 生成随机验证码
     *
     * @param length 验证码位数
     * @return
     */
    public static String getCaptcha(int length) {
        // 自定义纯数字的验证码(随机 4 位数字,可重复)
        RandomGenerator randomGenerator = new RandomGenerator("0123456789", length);
        LineCaptcha lineCaptcha = cn.hutool.captcha.CaptchaUtil.createLineCaptcha(200, 100);
        lineCaptcha.setGenerator(randomGenerator);
        // 重新生成 code
        lineCaptcha.createCode();
        return lineCaptcha.getCode();
    }
}

前后端交互接口

  • 请求:/verification-code/send?phoneNumber=13199999999 GET
  • 响应:
{
  "code": 200,
  "data": true,
  "msg": ""
}

Controller 层接口设计

  • 接收手机号参数,调用 VerificationCodeService 发送验证码,返回发送结果。

Service 层接口设计

  • VerificationCodeService 接口定义发送验证码和获取验证码的方法。
  • VerificationCodeServiceImpl 实现逻辑:
    1. 校验手机号格式。
    2. 生成验证码。
    3. 调用 SMSUtil 发送短信。
    4. 将验证码存入 Redis,设置 60 秒过期时间。

VerificationCodeServiceImpl 阿里云短信验证码服务类示例:

/**
 * 阿里云短信验证码服务类
 */
@Service
public class VerificationCodeServiceImpl implements VerificationCodeService {
    @Autowired
    private SMSUtil smsUtil;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 发送并缓存验证码
     *
     * @param phoneNumber
     */
    @Override
    public void sendVerificationCode(String phoneNumber) {
        // 校验手机号
        if (!RegexUtil.checkMobile(phoneNumber)) {
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }
        // 生成随机验证码,长度 4
        String code = CaptchaUtil.getCaptcha(Constants.CODE_LENGTH);
        // 发送验证码
        smsUtil.sendVerifyCode(phoneNumber, code);
        // 缓存验证码
        // 一个手机号对应一个验证码,再次接收会覆盖
        redisUtil.set(Constants.VERIFICATION_CODE_PREFIX + phoneNumber, code, Constants.VERIFICATION_CODE_TIMEOUT);
    }
}

3.2 Redis 的配置与使用

> 核心工具类 RedisUtil

基于 StringRedisTemplate 封装 Redis 操作,避免乱码问题,核心方法:

  • hasKey:判断键是否存在。
  • setExpire:设置键的过期时间。
  • getExpire:获取键的过期时间。
  • del:删除键。
  • get:获取字符串类型键的值。
  • set:设置字符串类型键的值(支持过期时间)。

RedisUtil 示例:

/**
 * Redis 工具缓存
 */
@Configuration
public class RedisUtil {
    private static final Logger logger = LoggerFactory.getLogger(RedisUtil.class);

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // --------- String ---------
    /**
     * 设置值
     *
     * @param key
     * @param value
     * @return
     */
    public boolean set(String key, String value) {
        try {
            stringRedisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            logger.error("RedisUtil error,set({}, {})", key, value, e);
            return false;
        }
    }

    /**
     * 设置值(可设置过期时间)
     *
     * @param key
     * @param value
     * @param time 单位:秒
     * @return
     */
    public boolean set(String key, String value, Long time) {
        try {
            stringRedisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            return true;
        } catch (Exception e) {
            logger.error("RedisUtil error,set({}, {}, {})", key, value, time, e);
            return false;
        }
    }

    /**
     * 获取值
     *
     * @param key
     * @return
     */
    public String get(String key) {
        try {
            return StringUtils.hasText(key) ? stringRedisTemplate.opsForValue().get(key) : null;
        } catch (Exception e) {
            logger.error("RedisUtil error,get({})", key, e);
            return null;
        }
    }
}

3.3 JWT

采用 JWT(JSON Web Token)实现无状态登录,解决集群环境下 Session 共享问题。

> JWT 令牌介绍

JWT 全称:JSON Web Token,官网:https://jwt.io/

JSON Web Token (JWT) 是一个开放的行业标准 (RFC 7519),用于客户端和服务器之间传递安全可靠的信息。 其本质是一个 token,是一种紧凑的 URL 安全方法。

JWT 组成: JWT 由三部分组成,每部分中间使用点 (.) 分隔,例如:aaaaa.bbbbb.cccc

  • Header (头部) 头部包括令牌的类型(即 JWT)及使用的哈希算法(如 HMAC SHA256 或 RSA)。

Signature (签名) 此部分用于防止 JWT 内容被篡改,确保安全性。

防止被篡改,而不是防止被解析。

JWT 之所以安全,就是因为最后的签名。JWT 当中任何一个字符被篡改,整个令牌都会校验失败。 就好比身份证,之所以能标识一个人的身份,是因为它不能被篡改,而不是因为内容加密。(任何人都可以看到身份证的信息,JWT 也是)

Payload (负载) 负载部分是存放有效信息的地方,里面是一些自定义内容。比如:

{"userId":"123","userName":"zhangsan"}

也可以存在 JWT 提供的现成字段,比如 exp (过期时间戳) 等。

此部分不建议存放敏感信息,因为此部分可以解码还原原始内容。

> 核心工具类 JWTUtil
  • genJwt:生成 JWT 令牌,包含自定义载荷(用户 ID、身份)、签发时间、过期时间(1 小时),使用 HMAC SHA 算法签名。
  • parseJWT:解析 JWT 令牌,验证签名合法性,返回载荷信息。
  • getUserIdFromToken:从令牌中提取用户 ID。

JWTUtil 示例:

public class JWTUtil {
    private static final Logger logger = LoggerFactory.getLogger(JWTUtil.class);

    /**
     * 密钥:Base64 编码的密钥
     */
    private static final String SECRET = "********";

    /**
     * 生成安全密钥:将一个 Base64 编码的密钥解码并创建一个 HMAC SHA 密钥。
     */
    private static final SecretKey SECRET_KEY = Keys.hmacShaKeyFor(Decoders.BASE64.decode(SECRET));

    /**
     * 过期时间 (单位:毫秒)
     */
    private static final long EXPIRATION = 24 * 60 * 60 * 1000;

    /**
     * 生成密钥
     *
     * @param claim {"id": 12, "name":"张山"}
     * @return
     */
    public static String genJwt(Map<String, Object> claim) {
        // 签名算法
        String jwt = Jwts.builder()
                .setClaims(claim) // 自定义内容 (载荷)
                .setIssuedAt(new Date()) // 设置签发时间
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION)) // 设置过期时间
                .signWith(SECRET_KEY) // 签名算法
                .compact();
        return jwt;
    }

    /**
     * 验证密钥
     */
    public static Claims parseJWT(String jwt) {
        if (!StringUtils.hasLength(jwt)) {
            return null;
        }
        // 创建解析器,设置签名密钥
        JwtParserBuilder jwtParserBuilder = Jwts.parserBuilder().setSigningKey(SECRET_KEY);
        Claims claims = null;
        try {
            // 解析 token
            claims = jwtParserBuilder.build().parseClaimsJws(jwt).getBody();
        } catch (Exception e) {
            // 签名验证失败
            logger.error("解析令牌错误,jwt:{}", jwt, e);
        }
        return claims;
    }
}

3.4 管理员登录

支持'电话 + 密码'和'电话 + 验证码'两种登录方式,基于 JWT 返回令牌。

登录流程:

  1. 登陆页面把用户名密码提交给服务器。
  2. 服务器端验证用户名密码是否正确,如果正确,服务器生成令牌,下发给客户端。
  3. 客户端把令牌存储起来(比如 Cookie、local storage 等),后续请求时,把 token 发给服务器。
  4. 服务器对令牌进行校验,如果令牌正确,进行下一步操作。

前后端交互接口

  • 密码登录请求:/password/login POST
{
  "loginName": "13199999999",
  "password": "123456",
  "mandatoryIdentity": "ADMIN"
}
  • 密码登录响应:
{
  "code": 200,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiJ9...",
    "identity": "ADMIN"
  },
  "msg": ""
}
  • 验证码登录请求:/message/login POST
{
  "loginMobile": "13199999999",
  "verificationCode": "0475",
  "mandatoryIdentity": "ADMIN"
}
  • 验证码登录响应:
{
  "code": 200,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiJ9...",
    "identity": "ADMIN"
  },
  "msg": ""
}

Controller 层接口设计

  • 提供两个登录接口,分别处理密码登录和验证码登录。
  • 接收登录参数,通过 @Validated 校验,调用 UserService 完成登录逻辑,返回 UserLoginResult(含 token 和身份)。
  • 核心类:
    • UserPasswordLoginParam:密码登录入参(登录名、密码、强制身份)。
    • ShortMessageLoginParam:验证码登录入参(手机号、验证码、强制身份)。
    • UserLoginResult:登录出参(token、身份)。

Service 层接口设计

  • UserService 接口新增 login 方法,支持不同登录参数类型。
  • UserServiceImpl 实现逻辑:
    1. 区分登录类型(密码登录/验证码登录)。
    2. 密码登录:校验登录名格式(邮箱/手机号)、查询用户信息、校验身份、校验密码,生成 JWT 令牌。
    3. 验证码登录:校验手机号格式、查询用户信息、校验身份、校验验证码(从 Redis 获取),生成 JWT 令牌。

Dao 层接口设计

  • UserMapper 新增接口:
    • selectByEmail:通过邮箱查询用户信息。
    • selectByPhoneNumber:通过手机号查询用户信息。

登录页面前端实现

  • 支持 tab 切换两种登录方式(密码登录/验证码登录)。
  • 使用 jQuery Validate 校验表单字段(手机号、密码/验证码必填)。
  • 验证码登录支持 60 秒倒计时重新获取。
  • 登录成功后,将 token 和身份存入 localStorage,跳转管理员首页。

四、强制登录

通过拦截器实现非登录页面的强制登录校验。例如,当用户当前尚未登陆,访问抽奖页时希望自动跳转到登录页面。

4.1 前端处理
  • 所有 AJAX 请求通过 ajaxSend 方法在请求头中添加 user_token(从 localStorage 获取),让后端取校验。
  • 若请求返回 401(未登录),跳转至登录页(含 iframe 框架场景处理)。
4.2 后端处理

登录拦截器 LoginInterceptor

实现 HandlerInterceptor,重写 preHandle 方法:

  • 从请求头获取 user_token。
  • 调用 JWTUtil 解析令牌,校验合法性。
  • 令牌无效或不存在时,返回 401 状态码,拦截请求。

拦截器类示例:

/**
 * 登录拦截器
 * */
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * 预处理,业务请求前调用
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取请求头
        String token = request.getHeader("user_token");
        log.info("获取 Token: {}", token);
        log.info("获取请求路径:{}", request.getRequestURI());

        // 令牌解析
        Claims claims = JWTUtil.parseJWT(token);
        if (null == claims) {
            log.error("解析 JWT 令牌失败!");
            response.setStatus(401);
            return false;
        }
        log.info("解析 JWT 令牌成功!");
        return true;
    }
}

配置类 AppConfig

实现 WebMvcConfigurer,配置拦截器:

  • 拦截所有请求(/**)。
  • 排除登录、注册、验证码发送等接口,以及静态资源(HTML、CSS、JS 等)。

拦截器排除路径示例:

/**
 * 拦截器排除路径
 * */
@Configuration
public class AppConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;

    private final List<String> excludes = Arrays.asList(
        "/**.html",
        "/css/**",
        "/js/**",
        "/pic/**",
        "/*.jpg",
        "/*.png",
        "/favicon.ico",
        "/**/login",
        "/register",
        "/verification-code/send",
        "/winning-records/show"
    );

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns(excludes);
    }
}

五、用户管理

5.1 后台管理页面

  • 管理员首页(admin.html)通过 iframe 加载子页面,支持导航菜单切换。
  • 监听子页面消息,实现子页面向父页面传递跳转指令。
  • 提供退出登录功能,清除 localStorage 中的 token,跳转登录页。

5.2 注册用户(管理员新增)

  • 前端逻辑与普通注册类似,但新增用户后直接跳转到用户列表页。
  • 通过 URL 参数 jumpList 控制跳转行为,admin 参数控制用户身份。

5.3 人员列表展示

前后端交互接口

  • 请求:/base-user/find-list GET(可选参数 identity 筛选身份)
  • 响应:
{
  "code": 200,
  "data": [
    {
      "userId": 15,
      "userName": "郭靖",
      "identity": "NORMAL"
    },
    {
      "userId": 14,
      "userName": "王五",
      "identity": "ADMIN"
    }
  ],
  "msg": ""
}

Controller 层接口设计

  • 接收身份筛选参数,调用 UserService 查询用户列表,转换为 UserBaseInfoResult 返回。

Service 层接口设计

  • UserService 新增 findUserList 方法,支持按身份筛选(null 查询所有)。
  • UserServiceImpl 实现逻辑:查询用户列表,转换为 UserDTO,包含用户 ID、姓名、邮箱、手机号、身份。

Dao 层接口设计

  • UserMapper 新增 selectUserList 方法,支持按身份查询用户列表,按 ID 降序排序。

人员列表页面前端实现

  • 页面加载时通过 AJAX 请求 /base-user/find-list 接口,获取用户列表。
  • 渲染表格展示用户 ID、姓名、身份。
  • 未登录时跳转至登录页。

目录

  1. 一、注册
  2. 1.1 敏感字段加密
  3. 1.2 用户注册
  4. 1.3 TypeHandler
  5. 二、控制层通用异常处理
  6. 三、登录
  7. 3.1 发送验证码
  8. 3.2 Redis 的配置与使用
  9. > 核心工具类 RedisUtil
  10. 3.3 JWT
  11. > JWT 令牌介绍
  12. > 核心工具类 JWTUtil
  13. 3.4 管理员登录
  14. 四、强制登录
  15. 4.1 前端处理
  16. 4.2 后端处理
  17. 五、用户管理
  18. 5.1 后台管理页面
  19. 5.2 注册用户(管理员新增)
  20. 5.3 人员列表展示

更多推荐文章

查看全部
  • C++ 网络模块兼容性优化的 7 个关键步骤
  • Linux GCC/G++编译器:从源码到可执行文件的全流程解析
  • OpenClaw 搭建有记忆与性格的私人 AI 助手配置指南
  • Seedance 2.0 实测:影视级 AI 视频生成的商业化落地
  • Linux 基础 IO:文件描述符、重定向与缓冲区原理
  • Microi 吾码低代码平台技术架构与集成实践
  • 互联网后端开发核心面试题精选(MySQL/Java/Spring)
  • 网络安全入门:黑客必须掌握的核心技术
  • Linux 命令行核心实战:Git 提交、权限控制与常用快捷键
  • 从零手搓中文大模型 Day04:模型参数配置和训练启动
  • OpenClaw 本地部署教程:环境配置、插件开发与常见问题排查
  • 从零搭建 Clawdbot 对接企业微信机器人单向推送指南
  • 八种常见排序算法详解与实现
  • Paper Minecraft V3.0 下界更新:基于 C++ 的 2D 控制台版我的世界实现
  • Java 后端转 Web3 实战路线图
  • 使用 Anthropic Skill 提升大模型前端设计质量
  • Test-Agent:开源软件测试智能助手
  • 使用 ISAAC Lab 训练机器人行走
  • 基于 OpenCASCADE 的分层截面几何体重建与 STL 导出
  • Harness Engineering:AI Agent 时代软件工程的范式转变

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online