- 完善注册功能
- 完善全局异常处理器
This commit is contained in:
yulinling 2025-06-19 21:53:33 +08:00
parent 8937ec945a
commit 7fa1a38e33
9 changed files with 177 additions and 21 deletions

View File

@ -56,8 +56,8 @@ public class SecurityConfig {
)
// 认证请求
.authorizeHttpRequests(auth -> auth
.requestMatchers("/login").permitAll()
// .requestMatchers("/users", "/users/**").hasRole("ADMIN")
.requestMatchers("/auth/**").permitAll()
.requestMatchers("/auth/register").permitAll()
.anyRequest().access((authenticationSupplier, requestAuthorizationContext) -> {
HttpServletRequest request = requestAuthorizationContext.getRequest();
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

View File

@ -1,15 +1,18 @@
package asia.yulinling.workflow.controller;
import asia.yulinling.workflow.dto.request.LoginRequest;
import asia.yulinling.workflow.dto.request.RegisterRequest;
import asia.yulinling.workflow.dto.response.JWTAuthResponse;
import asia.yulinling.workflow.model.ApiResponse;
import asia.yulinling.workflow.service.AuthService;
import asia.yulinling.workflow.utils.ResponseUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
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;
/**
@ -22,16 +25,27 @@ import org.springframework.web.bind.annotation.RestController;
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/auth")
@Slf4j
public class AuthController {
private final AuthService authenticate;
private final AuthService authService;
@PostMapping("/login")
public ApiResponse<JWTAuthResponse> login(@RequestBody LoginRequest loginRequest) {
String token = authenticate.login(loginRequest);
String token = authService.login(loginRequest);
JWTAuthResponse jwtAuthResponse = new JWTAuthResponse(token);
return ApiResponse.ofSuccess(jwtAuthResponse);
}
@PostMapping("/logout")
public ApiResponse<?> logout(HttpServletRequest request) throws SecurityException {
return authService.logout(request);
}
@PostMapping("/register")
public ApiResponse<?> register(@RequestBody RegisterRequest registerRequest) throws Exception {
return authService.register(registerRequest);
}
}

View File

@ -0,0 +1,65 @@
package asia.yulinling.workflow.dto.request;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
/**
* <p>
* 注册请求类
* </p>
*
* @author YLL
* @since 2025/6/19
*/
@Data
public class RegisterRequest {
/**
* 用户名
*/
@NotBlank(message = "用户名不能为空")
private String username;
/**
* 昵称
*/
private String nickname;
/**
* 密码
*/
@NotBlank(message = "密码不能为空")
private String password;
/**
* 二次密码
*/
@NotBlank(message = "确认密码不能为空")
private String confirmPassword;
/**
* 电子邮箱
*/
@Email
private String email;
/**
* 生日
*/
private String birthday;
/**
* 性别
*/
private Integer sex;
/**
* 手机号
*/
@Max(11)
@Min(5)
private String phone;
}

View File

@ -1,9 +1,12 @@
package asia.yulinling.workflow.exception.handler;
import asia.yulinling.workflow.exception.BaseException;
import asia.yulinling.workflow.exception.JsonException;
import asia.yulinling.workflow.exception.PageException;
import asia.yulinling.workflow.model.ApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ -30,9 +33,9 @@ public class GlobalExceptionHandler {
*/
@ExceptionHandler(Exception.class)
@ResponseBody
public ApiResponse<?> jsonErrorHandler(JsonException e) {
log.error(e.getMessage());
return ApiResponse.ofException(e);
public ApiResponse<?> cathAllErrorHandler(Exception e) {
log.error("json error:{}", e.getMessage());
return ApiResponse.of(500, e.getMessage(), null);
}
/**

View File

@ -56,7 +56,7 @@ public class ApiResponse<T> {
* @param data 返回数据
* @return ApiResponse
*/
public static <T> ApiResponse<T> of(Integer code, String message, T data) {
public static <T> ApiResponse<T> of(Integer code, String message, Object data) {
return new ApiResponse<>(code, message, data);
}
@ -109,7 +109,7 @@ public class ApiResponse<T> {
* @param <T> {@link BaseException} 子类
* @return ApiResponse
*/
public static <T extends BaseException> ApiResponse<T> ofException(T t, T data) {
public static <T extends BaseException> ApiResponse<T> ofException(T t, Object data) {
return of(t.getCode(), t.getMessage(), data);
}

View File

@ -5,6 +5,7 @@ import asia.yulinling.workflow.model.ApiResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
@ -20,6 +21,7 @@ import java.io.IOException;
* @since 2025/6/13
*/
@Component
@Slf4j
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
private final ObjectMapper objectMapper;
@ -31,6 +33,8 @@ public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
log.error("AuthenticationException: {}",authException.getMessage());
// 1. 设置res 401
response.setContentType("application/json;charset=UTF-8");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

View File

@ -1,6 +1,9 @@
package asia.yulinling.workflow.service;
import asia.yulinling.workflow.dto.request.LoginRequest;
import asia.yulinling.workflow.dto.request.RegisterRequest;
import asia.yulinling.workflow.model.ApiResponse;
import jakarta.servlet.http.HttpServletRequest;
/**
* <p>
@ -12,4 +15,8 @@ import asia.yulinling.workflow.dto.request.LoginRequest;
*/
public interface AuthService {
String login(LoginRequest loginRequest);
ApiResponse<?> logout(HttpServletRequest request) throws SecurityException;
ApiResponse<?> register(RegisterRequest request) throws Exception;
}

View File

@ -1,15 +1,29 @@
package asia.yulinling.workflow.service.impl;
import asia.yulinling.workflow.constant.Status;
import asia.yulinling.workflow.dto.request.LoginRequest;
import asia.yulinling.workflow.dto.request.RegisterRequest;
import asia.yulinling.workflow.mapper.UserMapper;
import asia.yulinling.workflow.model.ApiResponse;
import asia.yulinling.workflow.model.entity.User;
import asia.yulinling.workflow.service.AuthService;
import asia.yulinling.workflow.utils.JwtUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.Date;
/**
* <p>
@ -26,6 +40,8 @@ public class AuthServiceImpl implements AuthService {
private final AuthenticationManager authenticationManager;
private final JwtUtil jwtUtil;
private final PasswordEncoder passwordEncoder;
private final UserMapper userMapper;
@Override
public String login(LoginRequest loginRequest) {
@ -33,8 +49,55 @@ public class AuthServiceImpl implements AuthService {
loginRequest.getUsername(), loginRequest.getPassword()
));
SecurityContextHolder.getContext().setAuthentication(authentication);
String token =jwtUtil.generateToken(authentication, false);
String token = jwtUtil.generateToken(authentication, false);
log.info("generateToken: {}", token);
return token;
}
@Override
public ApiResponse<?> logout(HttpServletRequest request) throws SecurityException {
try {
jwtUtil.invalidateToken(request);
} catch (SecurityException e) {
log.info("invalidateToken: {}", e.getMessage());
}
return ApiResponse.ofStatus(Status.LOGOUT);
}
@Override
public ApiResponse<?> register(RegisterRequest request) throws Exception {
if (!StrUtil.equals(request.getConfirmPassword(), request.getPassword())) {
log.info("password {}, confirmPassword {}", request.getConfirmPassword(), request.getPassword());
return ApiResponse.of(400, "密码不一致", null);
}
if (userMapper.exists(new LambdaQueryWrapper<User>().eq(User::getUsername, request.getUsername()))) {
return ApiResponse.of(400, "用户名已存在", null);
}
if (userMapper.exists(new LambdaQueryWrapper<User>().eq(User::getEmail, request.getEmail()))) {
return ApiResponse.of(400, "邮箱已注册", null);
}
User user = new User();
user.setUsername(request.getUsername());
user.setPassword(passwordEncoder.encode(request.getPassword()));
user.setEmail(request.getEmail());
user.setNickname(request.getNickname());
user.setPhone(request.getPhone());
user.setBirthday(request.getBirthday());
user.setStatus(1);
user.setUpdateTime(new Date());
log.info("User: {}", user);
try {
userMapper.insert(user);
} catch (Exception e) {
log.error("insertUser Error: {}", e.getMessage());
throw new RuntimeException(e);
}
return ApiResponse.of(200, "注册成功", null);
}
}

View File

@ -3,9 +3,9 @@ CREATE TABLE `wk_user`
(
`id` bigint(64) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '主键',
`username` VARCHAR(32) NOT NULL UNIQUE COMMENT '用户名',
`nickname` VARCHAR(32) NOT NULL UNIQUE COMMENT '昵称',
`nickname` VARCHAR(32) DEFAULT '默认用户' COMMENT '昵称',
`password` VARCHAR(256) NOT NULL COMMENT '加密后的密码',
`email` VARCHAR(32) NOT NULL UNIQUE COMMENT '邮箱',
`email` VARCHAR(32) UNIQUE COMMENT '邮箱',
`birthday` DATETIME DEFAULT NULL COMMENT '生日',
`sex` INT(2) DEFAULT NULL COMMENT '性别,男-1,女-2',
`phone` VARCHAR(15) DEFAULT NULL UNIQUE COMMENT '手机号',