3.10、用户模块实现
分类: 搭建单体商城服务
用户模块实现
用户模块是商城系统的基础模块,包括用户注册、登录、信息查询等功能。本节将学习如何实现完整的用户模块。
本节将学习:用户注册、用户登录、用户信息查询,以及密码加密(BCrypt)。
用户注册
注册流程
注册实现
package com.example.ecommerce.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.ecommerce.entity.User; import com.example.ecommerce.exception.BusinessException; import com.example.ecommerce.mapper.UserMapper; import com.example.ecommerce.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Autowired private PasswordEncoder passwordEncoder; @Override @Transactional(rollbackFor = Exception.class) public User register(User user) { // 1. 检查用户名是否已存在 User existUser = baseMapper.selectOne( new LambdaQueryWrapper<User>() .eq(User::getUsername, user.getUsername()) ); if (existUser != null) { throw new BusinessException("Username already exists"); } // 2. 检查邮箱是否已存在 existUser = baseMapper.selectOne( new LambdaQueryWrapper<User>() .eq(User::getEmail, user.getEmail()) ); if (existUser != null) { throw new BusinessException("Email already exists"); } // 3. 加密密码 user.setPassword(passwordEncoder.encode(user.getPassword())); // 4. 设置默认状态 user.setStatus(1); // 5. 保存用户 save(user); return user; } }
Controller 实现
@PostMapping("/register") public Result<User> register(@RequestBody @Valid User user) { User registered = userService.register(user); return Result.success("User registered successfully", registered); }
用户登录
登录流程
登录实现
@Override public User login(String username, String password) { // 1. 根据用户名查询用户 User user = baseMapper.selectOne( new LambdaQueryWrapper<User>() .eq(User::getUsername, username) ); if (user == null) { throw new BusinessException("Invalid username or password"); } // 2. 检查用户状态 if (user.getStatus() == 0) { throw new BusinessException("User is disabled"); } // 3. 验证密码 if (!passwordEncoder.matches(password, user.getPassword())) { throw new BusinessException("Invalid username or password"); } return user; }
Controller 实现
@PostMapping("/login") public Result<User> login(@RequestParam String username, @RequestParam String password) { User user = userService.login(username, password); return Result.success("Login successful", user); }
用户信息查询
查询实现
@Override public User getById(Long id) { User user = super.getById(id); if (user == null) { throw new BusinessException("User not found"); } // 清除敏感信息 user.setPassword(null); return user; } @Override public User getByUsername(String username) { return baseMapper.selectOne( new LambdaQueryWrapper<User>() .eq(User::getUsername, username) ); } @Override public User getByEmail(String email) { return baseMapper.selectOne( new LambdaQueryWrapper<User>() .eq(User::getEmail, email) ); }
Controller 实现
@GetMapping("/{id}") public Result<User> getUser(@PathVariable Long id) { User user = userService.getById(id); return Result.success(user); } @GetMapping("/username/{username}") public Result<User> getUserByUsername(@PathVariable String username) { User user = userService.getByUsername(username); if (user == null) { throw new BusinessException("User not found"); } return Result.success(user); }
密码加密(BCrypt)
BCrypt 简介
BCrypt 是一种密码哈希函数,专门用于密码存储。它使用盐值(salt)和可配置的成本因子,提供强大的密码加密。
PasswordEncoder 配置
package com.example.ecommerce.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class SecurityConfig { @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
密码加密使用
@Autowired private PasswordEncoder passwordEncoder; // 加密密码 String encodedPassword = passwordEncoder.encode("plainPassword"); // 验证密码 boolean matches = passwordEncoder.matches("plainPassword", encodedPassword);
密码更新
@Override @Transactional(rollbackFor = Exception.class) public boolean updatePassword(Long userId, String oldPassword, String newPassword) { User user = getById(userId); if (user == null) { throw new BusinessException("User not found"); } // 验证旧密码 if (!passwordEncoder.matches(oldPassword, user.getPassword())) { throw new BusinessException("Invalid old password"); } // 加密新密码 user.setPassword(passwordEncoder.encode(newPassword)); // 更新密码 return updateById(user); }
完整用户模块示例
UserService 接口
package com.example.ecommerce.service; import com.baomidou.mybatisplus.extension.service.IService; import com.example.ecommerce.entity.User; public interface UserService extends IService<User> { User register(User user); User login(String username, String password); User getByUsername(String username); User getByEmail(String email); boolean updatePassword(Long userId, String oldPassword, String newPassword); boolean updateProfile(Long userId, User user); }
UserController 完整示例
package com.example.ecommerce.controller; import com.example.ecommerce.common.Result; import com.example.ecommerce.entity.User; import com.example.ecommerce.service.UserService; import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api/users") public class UserController { @Autowired private UserService userService; @PostMapping("/register") public Result<User> register(@RequestBody @Valid User user) { User registered = userService.register(user); return Result.success("User registered successfully", registered); } @PostMapping("/login") public Result<User> login(@RequestParam String username, @RequestParam String password) { User user = userService.login(username, password); return Result.success("Login successful", user); } @GetMapping("/{id}") public Result<User> getUser(@PathVariable Long id) { User user = userService.getById(id); return Result.success(user); } @PutMapping("/{id}") public Result<User> updateUser(@PathVariable Long id, @RequestBody @Valid User user) { user.setId(id); userService.updateById(user); return Result.success("User updated successfully", user); } @PutMapping("/{id}/password") public Result<?> updatePassword(@PathVariable Long id, @RequestParam String oldPassword, @RequestParam String newPassword) { userService.updatePassword(id, oldPassword, newPassword); return Result.success("Password updated successfully"); } }
官方资源
- Spring Security PasswordEncoder:https://docs.spring.io/spring-security/reference/features/authentication/password-storage.html
- BCrypt 算法:https://en.wikipedia.org/wiki/Bcrypt
本节小结
在本节中,我们实现了:
第一个是用户注册。 检查用户名和邮箱是否已存在,加密密码后保存用户。
第二个是用户登录。 验证用户名和密码,检查用户状态。
第三个是用户信息查询。 根据 ID、用户名、邮箱查询用户信息。
第四个是密码加密。 使用 BCrypt 加密密码,确保密码安全。
这就是用户模块实现。用户模块是系统的基础,为其他模块提供用户认证和授权支持。
在下一节,我们将学习如何实现商品模块,包括商品管理、商品搜索等功能。