文章目录
1.登录功能-后端
1.思路分析
2.完成对用户名和密码的校验
java
复制代码
public Long userRegister(String userAccount, String userPassword, String checkPassword);
/**
* 用户登录接口
* @param userAccount 账号
* @param userPassword 密码
* @return 成功返回脱敏后的User对象,失败返回null
*/
public User doLogin(String userAccount, String userPassword);
java
复制代码
@Override
public User doLogin(String userAccount, String userPassword) {
// 1 检验用户名和密码是否合法,如果不合法就没必要去数据库查询
// 验证非空
if (StringUtils.isAnyBlank(userAccount, userPassword)) {
return null;
}
// 账户4到16位,不能包含特殊字符
if (!userAccount.matches("^[a-zA-Z0-9]{4,16}$")) {
return null;
}
// 密码不小于8位
if (userPassword.length() < 8) {
return null;
}
// 2 密码加密进行查询
String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
// 编写查询条件
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.eq("userPassword", encryptPassword);
userQueryWrapper.eq("userAccount", userAccount);
// 执行查询
User user = userMapper.selectOne(userQueryWrapper);
// 判断用户是否存在
if (user == null) {
// 输出日志
log.info("user login faild, userAccount can not match password");
return null;
}
// 3 记录用户的登录态
return user;
}
3.记录用户的登录态并配置MyBatisPlus的逻辑删除
java
复制代码
/**
* 用户登录接口
* @param userAccount 账号
* @param userPassword 密码
* @return 成功返回脱敏后的User对象,失败返回null
*/
public User doLogin(String userAccount, String userPassword, HttpServletRequest request);
doLogin 方法添加代码,记录用户登录态
java
复制代码
// 3 如果登录成功,记录用户的登录态
// 首先进行脱敏
User cleanUser = new User();
cleanUser.setId(user.getId());
cleanUser.setUsername(user.getUsername());
cleanUser.setUserAccount(user.getUserAccount());
cleanUser.setAvatarUrl(user.getAvatarUrl());
cleanUser.setGender(user.getGender());
cleanUser.setPhone(user.getPhone());
cleanUser.setEmail(user.getEmail());
cleanUser.setUserStatus(user.getUserStatus());
cleanUser.setCreateTime(user.getCreateTime());
HttpSession session = request.getSession();
// 然后将脱敏后的用户信息放入session中
session.setAttribute(USER_LOGIN_SAVE, cleanUser);
return cleanUser;
4.配置MyBatisPlus的逻辑删除
1.application.yml 配置
yaml
复制代码
global-config:
db-config:
logic-delete-field: isDelete # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
2.实体类添加注解
2.接口开发及测试
java
复制代码
package com.sun.usercenter.controller;
import com.sun.usercenter.model.domain.User;
import com.sun.usercenter.model.request.UserLoginRequest;
import com.sun.usercenter.model.request.UserRegisterRequest;
import com.sun.usercenter.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
/**
* Description:
*
* @Author sun
* @Create 2024/3/21 13:04
* @Version 1.0
*/
@RestController // 作为一个Controller注入容器,并将返回结果转换为json
@RequestMapping("/user") // restful风格的请求
public class UserController {
@Resource
private UserService userService; // 注入针对Service接口的bean对象,可以调用接口的方法
@PostMapping("/register")
public Long userRegister(@RequestBody UserRegisterRequest userRegisterRequest) {
// 首先判断数据是否成功封装
if (userRegisterRequest == null) {
return null;
}
// 对封装的数据进行校验,如果有一个是空直接返回null
String userAccount = userRegisterRequest.getUserAccount();
String userPassword = userRegisterRequest.getUserPassword();
String checkPassword = userRegisterRequest.getCheckPassword();
if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) {
return null;
}
// 调用Service层的注册方法,如果成功注册,则返回注册成功的用户id, 否则返回-1
return userService.userRegister(userAccount, userPassword, checkPassword);
}
@PostMapping("/login")
public User userRegister(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request) {
// 首先判断数据是否成功封装
if (userLoginRequest == null) {
return null;
}
// 对封装的数据进行校验,如果有一个是空直接返回null
String userAccount = userLoginRequest.getUserAccount();
String userPassword = userLoginRequest.getUserPassword();
if (StringUtils.isAnyBlank(userAccount, userPassword)) {
return null;
}
return userService.doLogin(userAccount, userPassword, request);
}
}
2.封装登录和注册请求信息的对象
1.文件目录
java
复制代码
package com.sun.usercenter.model.request;
import lombok.Data;
/**
* Description: 用户登录请求体
*
* @Author sun
* @Create 2024/3/21 13:39
* @Version 1.0
*/
@Data
public class UserLoginRequest {
private String userAccount;
private String userPassword;
}
java
复制代码
package com.sun.usercenter.model.request;
import lombok.Data;
/**
* Description: 用户注册请求体
*
* @Author sun
* @Create 2024/3/21 13:26
* @Version 1.0
*/
@Data
public class UserRegisterRequest {
private String userAccount;
private String userPassword;
private String checkPassword;
}
3.单元测试
1.用户注册接口测试
1.debug模式启动IDEA
2.postman测试
2.用户登录接口测试
2.postman测试
3.查看session是否有用户登录状态的信息
4.放行,查看postman的返回结果
3.逻辑删除测试
1.在数据库中把刚才进行登录的用户id改成1
2.重新登录一下
3.用户管理接口
java
复制代码
/**
* 根据用户名进行模糊查询
*
* @param username
* @return 成功返回信息,失败返回null
*/
@GetMapping("/search")
public List<User> searchUsers(String username) {
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
if (StringUtils.isNotBlank(username)) {
userQueryWrapper.like("username", username);
}
return userService.list(userQueryWrapper);
}
/**
* 根据id进行逻辑删除(只要配置了MyBatisPlus的逻辑删除即可进行自动逻辑删除)
*
* @param id
* @return 成功返回true,失败返回false
*/
@PostMapping("/delete")
public boolean deleteUser(@RequestBody Long id) {
if (id <= 0) {
return false;
}
return userService.removeById(id); // 这里会自动逻辑删除
}
2.user表新增字段role表示用户权限
1.新增字段role
3.Mapper.xml不用修改,因为这个字段本来就与表的字段对应
java
复制代码
package com.sun.usercenter.contant;
/**
* Description: 用户常量
*
* @Author sun
* @Create 2024/3/21 15:14
* @Version 1.0
*/
public interface UserConstant {
/*
用户登录状态
*/
String USER_LOGIN_SAVE = "userLoginState";
// 用户权限
/*
默认权限
*/
Integer DEFAULT_ROLE = 0;
/*
管理员权限
*/
Integer ADMIN_ROLE = 1;
}
1.添加方法 isAdmin 判断是否为管理员
java
复制代码
/**
* 判断是否是管理员
* @param request
* @return 布尔
*/
public boolean isAdmin(HttpServletRequest request) {
User user = (User) request.getSession().getAttribute(USER_LOGIN_SAVE);
return user != null && user.getRole() == ADMIN_ROLE;
}
2.修改两个接口的方法
java
复制代码
/**
* 根据用户名进行模糊查询
*
* @param username
* @return 成功返回信息,失败返回null
*/
@GetMapping("/search")
public List<User> searchUsers(String username, HttpServletRequest request) {
// 仅管理员可查询
if (!isAdmin(request)) {
return new ArrayList<>();
}
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
if (StringUtils.isNotBlank(username)) {
userQueryWrapper.like("username", username);
}
return userService.list(userQueryWrapper);
}
/**
* 根据id进行逻辑删除(只要配置了MyBatisPlus的逻辑删除即可进行自动逻辑删除)
*
* @param id
* @return 成功返回true,失败返回false
*/
@PostMapping("/delete")
public boolean deleteUser(long id, HttpServletRequest request) {
// 仅管理员可删除
if (!isAdmin(request)) {
return false;
}
if (id <= 0) {
return false;
}
return userService.removeById(id); // 这里会自动逻辑删除
}
5.application.yml 设置session超时时间
6.单元测试
1.测试 searchUsers接口
1.登录
2.表中增加两条测试记录
3.进行查询,成功查询!
2.测试deleteUser接口
1.删除id为1的用户
2.查看数据库,成功进行逻辑删除
3.解决 searchUsers接口返回的用户信息没有脱敏的问题
java
复制代码
/**
* 进行用户信息脱敏
* @param user
* @return
*/
User getCleanUser(User user);
java
复制代码
/**
* 对得到的user对象,进行用户信息脱敏
* @param user
* @return
*/
@Override
public User getCleanUser(User user) {
User cleanUser = new User();
cleanUser.setId(user.getId());
cleanUser.setUsername(user.getUsername());
cleanUser.setUserAccount(user.getUserAccount());
cleanUser.setAvatarUrl(user.getAvatarUrl());
cleanUser.setGender(user.getGender());
cleanUser.setPhone(user.getPhone());
cleanUser.setEmail(user.getEmail());
cleanUser.setUserStatus(user.getUserStatus());
cleanUser.setCreateTime(user.getCreateTime());
cleanUser.setRole(user.getRole());
return cleanUser;
}
java
复制代码
/**
* 根据用户名进行模糊查询
*
* @param username
* @return 成功返回信息,失败返回null
*/
@GetMapping("/search")
public List<User> searchUsers(String username, HttpServletRequest request) {
// 仅管理员可查询
if (!isAdmin(request)) {
return new ArrayList<>();
}
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
if (StringUtils.isNotBlank(username)) {
userQueryWrapper.like("username", username);
}
List<User> userList = userService.list(userQueryWrapper);
// 将查询到的用户数据进行脱敏
// 这里的逻辑就是把查询到User对象列表使用user来遍历然后对每个user对象进行脱敏最后组合成一个新的list
return userList.stream().map(user -> {
return userService.getCleanUser(user);
}).collect(Collectors.toList());
}
4.再次测试,敏感信息变成null了