3.4 用户登录、校验
This commit is contained in:
parent
3ff8188dd8
commit
b0cf0b54ab
@ -0,0 +1,16 @@
|
|||||||
|
package edu.whut.smilepicturebackend.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface AuthCheck {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 必须具有某个角色
|
||||||
|
**/
|
||||||
|
String mustRole() default "";
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package edu.whut.smilepicturebackend.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户常量
|
||||||
|
*/
|
||||||
|
public interface UserConstant {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登录态键
|
||||||
|
*/
|
||||||
|
String USER_LOGIN_STATE = "user_login";
|
||||||
|
|
||||||
|
// region 权限
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认角色
|
||||||
|
*/
|
||||||
|
String DEFAULT_ROLE = "user";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员角色
|
||||||
|
*/
|
||||||
|
String VIP_ROLE = "vip";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员角色
|
||||||
|
*/
|
||||||
|
String ADMIN_ROLE = "admin";
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
}
|
@ -4,13 +4,15 @@ import edu.whut.smilepicturebackend.common.BaseResponse;
|
|||||||
import edu.whut.smilepicturebackend.common.ResultUtils;
|
import edu.whut.smilepicturebackend.common.ResultUtils;
|
||||||
import edu.whut.smilepicturebackend.exception.ErrorCode;
|
import edu.whut.smilepicturebackend.exception.ErrorCode;
|
||||||
import edu.whut.smilepicturebackend.exception.ThrowUtils;
|
import edu.whut.smilepicturebackend.exception.ThrowUtils;
|
||||||
|
import edu.whut.smilepicturebackend.model.dto.UserLoginRequest;
|
||||||
import edu.whut.smilepicturebackend.model.dto.UserRegisterRequest;
|
import edu.whut.smilepicturebackend.model.dto.UserRegisterRequest;
|
||||||
|
import edu.whut.smilepicturebackend.model.entity.User;
|
||||||
|
import edu.whut.smilepicturebackend.model.vo.LoginUserVO;
|
||||||
import edu.whut.smilepicturebackend.service.UserService;
|
import edu.whut.smilepicturebackend.service.UserService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@ -31,4 +33,36 @@ public class UserController {
|
|||||||
long result = userService.userRegister(userAccount, userPassword, checkPassword);
|
long result = userService.userRegister(userAccount, userPassword, checkPassword);
|
||||||
return ResultUtils.success(result);
|
return ResultUtils.success(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登录
|
||||||
|
*/
|
||||||
|
//TODO:目前是存在session中,待改为token JWT
|
||||||
|
@PostMapping("/login")
|
||||||
|
public BaseResponse<LoginUserVO> userLogin(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request) {
|
||||||
|
ThrowUtils.throwIf(userLoginRequest == null, ErrorCode.PARAMS_ERROR);
|
||||||
|
String userAccount = userLoginRequest.getUserAccount();
|
||||||
|
String userPassword = userLoginRequest.getUserPassword();
|
||||||
|
LoginUserVO loginUserVO = userService.userLogin(userAccount, userPassword, request);
|
||||||
|
return ResultUtils.success(loginUserVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前登录用户
|
||||||
|
*/
|
||||||
|
@GetMapping("/get/login")
|
||||||
|
public BaseResponse<LoginUserVO> getLoginUser(HttpServletRequest request) {
|
||||||
|
User loginUser = userService.getLoginUser(request);
|
||||||
|
return ResultUtils.success(userService.getLoginUserVO(loginUser));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户注销
|
||||||
|
*/
|
||||||
|
@PostMapping("/logout")
|
||||||
|
public BaseResponse<Boolean> userLogout(HttpServletRequest request) {
|
||||||
|
ThrowUtils.throwIf(request == null, ErrorCode.PARAMS_ERROR);
|
||||||
|
boolean result = userService.userLogout(request);
|
||||||
|
return ResultUtils.success(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package edu.whut.smilepicturebackend.model.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登录请求
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class UserLoginRequest implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 8735650154179439661L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号
|
||||||
|
*/
|
||||||
|
private String userAccount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
private String userPassword;
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package edu.whut.smilepicturebackend.model.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已登录用户视图(脱敏) isDelete和password没返回
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class LoginUserVO implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号
|
||||||
|
*/
|
||||||
|
private String userAccount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户头像
|
||||||
|
*/
|
||||||
|
private String userAvatar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户简介
|
||||||
|
*/
|
||||||
|
private String userProfile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户角色:user/admin
|
||||||
|
*/
|
||||||
|
private String userRole;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑时间
|
||||||
|
*/
|
||||||
|
private Date editTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
}
|
@ -2,6 +2,9 @@ package edu.whut.smilepicturebackend.service;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import edu.whut.smilepicturebackend.model.entity.User;
|
import edu.whut.smilepicturebackend.model.entity.User;
|
||||||
|
import edu.whut.smilepicturebackend.model.vo.LoginUserVO;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author 张三
|
* @author 张三
|
||||||
@ -25,6 +28,44 @@ public interface UserService extends IService<User> {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取加密后的密码
|
||||||
|
*
|
||||||
|
* @param userPassword
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
String getEncryptPassword(String userPassword);
|
String getEncryptPassword(String userPassword);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登录
|
||||||
|
*
|
||||||
|
* @param userAccount 用户账户
|
||||||
|
* @param userPassword 用户密码
|
||||||
|
* @return 脱敏后的用户信息
|
||||||
|
*/
|
||||||
|
LoginUserVO userLogin(String userAccount, String userPassword, HttpServletRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得脱敏后的登录用户信息
|
||||||
|
*
|
||||||
|
* @param user
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
LoginUserVO getLoginUserVO(User user);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前登录用户
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
User getLoginUser(HttpServletRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出登录
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean userLogout(HttpServletRequest request);
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,32 @@
|
|||||||
package edu.whut.smilepicturebackend.service.impl;
|
package edu.whut.smilepicturebackend.service.impl;
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import edu.whut.smilepicturebackend.constant.UserConstant;
|
||||||
import edu.whut.smilepicturebackend.exception.BusinessException;
|
import edu.whut.smilepicturebackend.exception.BusinessException;
|
||||||
import edu.whut.smilepicturebackend.exception.ErrorCode;
|
import edu.whut.smilepicturebackend.exception.ErrorCode;
|
||||||
import edu.whut.smilepicturebackend.model.entity.User;
|
import edu.whut.smilepicturebackend.model.entity.User;
|
||||||
import edu.whut.smilepicturebackend.model.enums.UserRoleEnum;
|
import edu.whut.smilepicturebackend.model.enums.UserRoleEnum;
|
||||||
|
import edu.whut.smilepicturebackend.model.vo.LoginUserVO;
|
||||||
import edu.whut.smilepicturebackend.service.UserService;
|
import edu.whut.smilepicturebackend.service.UserService;
|
||||||
import edu.whut.smilepicturebackend.mapper.UserMapper;
|
import edu.whut.smilepicturebackend.mapper.UserMapper;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author 张三
|
* @author 张三
|
||||||
* @description 针对表【user(用户)】的数据库操作Service实现
|
* @description 针对表【user(用户)】的数据库操作Service实现
|
||||||
* @createDate 2025-06-05 17:43:52
|
* @createDate 2025-06-05 17:43:52
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
|
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
|
||||||
implements UserService{
|
implements UserService{
|
||||||
@ -46,9 +55,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
|
|||||||
throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");
|
throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");
|
||||||
}
|
}
|
||||||
// 2. 检查用户账号是否和数据库中已有的重复
|
// 2. 检查用户账号是否和数据库中已有的重复
|
||||||
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
|
LambdaQueryWrapper<User> lambda = Wrappers.lambdaQuery();
|
||||||
queryWrapper.eq("userAccount", userAccount);
|
lambda.eq(User::getUserAccount, userAccount);
|
||||||
long count = this.baseMapper.selectCount(queryWrapper);
|
long count = this.baseMapper.selectCount(lambda);
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号重复");
|
throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号重复");
|
||||||
}
|
}
|
||||||
@ -79,6 +88,87 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User>
|
|||||||
// final String SALT = "smile12306";
|
// final String SALT = "smile12306";
|
||||||
// return DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
|
// return DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LoginUserVO userLogin(String userAccount, String userPassword, HttpServletRequest request) {
|
||||||
|
// 1. 校验
|
||||||
|
if (StrUtil.hasBlank(userAccount, userPassword)) {
|
||||||
|
throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
|
||||||
|
}
|
||||||
|
if (userAccount.length() < 4) {
|
||||||
|
throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号错误");
|
||||||
|
}
|
||||||
|
if (userPassword.length() < 8) {
|
||||||
|
throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码错误");
|
||||||
|
}
|
||||||
|
// 2. 对用户传递的密码进行加密
|
||||||
|
String encryptPassword = getEncryptPassword(userPassword);
|
||||||
|
// 3. 查询数据库中的用户是否存在
|
||||||
|
LambdaQueryWrapper<User> lambda = new LambdaQueryWrapper<>();
|
||||||
|
lambda
|
||||||
|
.eq(User::getUserAccount, userAccount)
|
||||||
|
.eq(User::getUserPassword, encryptPassword);
|
||||||
|
User user = this.baseMapper.selectOne(lambda);
|
||||||
|
// 不存在,抛异常
|
||||||
|
if (user == null) {
|
||||||
|
log.info("user login failed, userAccount cannot match userPassword");
|
||||||
|
throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在或者密码错误");
|
||||||
|
}
|
||||||
|
// 4. 保存用户的登录态
|
||||||
|
request.getSession().setAttribute(UserConstant.USER_LOGIN_STATE, user);
|
||||||
|
return this.getLoginUserVO(user);
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取脱敏类的用户信息
|
||||||
|
*
|
||||||
|
* @param user 用户
|
||||||
|
* @return 脱敏后的用户信息
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public LoginUserVO getLoginUserVO(User user) {
|
||||||
|
if (user == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
LoginUserVO loginUserVO = new LoginUserVO();
|
||||||
|
BeanUtil.copyProperties(user, loginUserVO);
|
||||||
|
return loginUserVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User getLoginUser(HttpServletRequest request) {
|
||||||
|
// 判断是否已经登录
|
||||||
|
Object userObj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
|
||||||
|
User currentUser = (User) userObj;
|
||||||
|
if (currentUser == null || currentUser.getId() == null) {
|
||||||
|
throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
|
||||||
|
}
|
||||||
|
// 从数据库中查询(追求性能的话可以注释,直接返回上述结果)
|
||||||
|
Long userId = currentUser.getId();
|
||||||
|
currentUser = this.getById(userId);
|
||||||
|
if (currentUser == null) {
|
||||||
|
throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
|
||||||
|
}
|
||||||
|
return currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出登录
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean userLogout(HttpServletRequest request) {
|
||||||
|
// 判断是否已经登录
|
||||||
|
Object userObj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
|
||||||
|
if (userObj == null) {
|
||||||
|
throw new BusinessException(ErrorCode.OPERATION_ERROR, "未登录");
|
||||||
|
}
|
||||||
|
// 移除登录态
|
||||||
|
request.getSession().removeAttribute(UserConstant.USER_LOGIN_STATE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ spring:
|
|||||||
password: 123456
|
password: 123456
|
||||||
|
|
||||||
mybatis-plus:
|
mybatis-plus:
|
||||||
|
type-aliases-package: edu.whut.smilepicturebackend.model.entity
|
||||||
configuration:
|
configuration:
|
||||||
# MyBatis 配置
|
# MyBatis 配置
|
||||||
map-underscore-to-camel-case: true #是否开启驼峰转换
|
map-underscore-to-camel-case: true #是否开启驼峰转换
|
||||||
|
27
src/main/resources/mapper/UserMapper.xml
Normal file
27
src/main/resources/mapper/UserMapper.xml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="edu.whut.smilepicturebackend.mapper.UserMapper">
|
||||||
|
|
||||||
|
<resultMap id="BaseResultMap" type="edu.whut.smilepicturebackend.model.entity.User">
|
||||||
|
<id property="id" column="id" jdbcType="BIGINT"/>
|
||||||
|
<result property="userAccount" column="user_account" jdbcType="VARCHAR"/>
|
||||||
|
<result property="userPassword" column="user_password" jdbcType="VARCHAR"/>
|
||||||
|
<result property="userName" column="user_name" jdbcType="VARCHAR"/>
|
||||||
|
<result property="userAvatar" column="user_avatar" jdbcType="VARCHAR"/>
|
||||||
|
<result property="userProfile" column="user_profile" jdbcType="VARCHAR"/>
|
||||||
|
<result property="userRole" column="user_role" jdbcType="VARCHAR"/>
|
||||||
|
<result property="editTime" column="edit_time" jdbcType="TIMESTAMP"/>
|
||||||
|
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
|
||||||
|
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
|
||||||
|
<result property="isDelete" column="is_delete" jdbcType="TINYINT"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
id,user_account,user_password,
|
||||||
|
user_name,user_avatar,user_profile,
|
||||||
|
user_role,edit_time,create_time,
|
||||||
|
update_time,is_delete
|
||||||
|
</sql>
|
||||||
|
</mapper>
|
Loading…
x
Reference in New Issue
Block a user