feat(auth): 实现登录认证和权限控制功能
- 添加用户登录和登出功能 - 实现 Token 过期和无效的错误处理 - 添加路由权限控制,未登录用户重定向到登录页 - 优化登录失败的错误提示 - 修复搜索功能的返回数据问题
This commit is contained in:
@@ -12,6 +12,8 @@ public enum ResultCode {
|
||||
FAILED(500, "操作失败"),
|
||||
VALIDATE_FAILED(400, "参数校验失败"),
|
||||
UNAUTHORIZED(401, "未授权"),
|
||||
TOKEN_EXPIRED(4011, "Token已过期"),
|
||||
TOKEN_INVALID(4012, "Token无效"),
|
||||
FORBIDDEN(403, "禁止访问"),
|
||||
NOT_FOUND(404, "资源不存在"),
|
||||
|
||||
|
||||
@@ -23,15 +23,15 @@ public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
public void commence(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
AuthenticationException authException) throws IOException, ServletException {
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setContentType("application/json");
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401
|
||||
|
||||
// 创建一个包含中文错误信息的R对象
|
||||
R<String> result = R.fail("认证失败,请重新登录");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setContentType("application/json");
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401
|
||||
|
||||
// 创建一个包含中文错误信息的R对象
|
||||
R<String> result = R.fail("认证失败,请重新登录");
|
||||
|
||||
// 使用ObjectMapper将对象转换为JSON字符串并写入响应
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
response.getWriter().write(objectMapper.writeValueAsString(result));
|
||||
}
|
||||
// 使用ObjectMapper将对象转换为JSON字符串并写入响应
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
response.getWriter().write(objectMapper.writeValueAsString(result));
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import io.swagger.v3.oas.annotations.Parameters;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@@ -57,10 +58,14 @@ public class UserController {
|
||||
})
|
||||
@PostMapping("/login")
|
||||
public R<Map<String, String>> login(String username, String password){
|
||||
String token = userService.login(username, password);
|
||||
Map<String, String> tokenMap = new HashMap<>();
|
||||
tokenMap.put("token", token);
|
||||
return R.success(tokenMap);
|
||||
try {
|
||||
String token = userService.login(username, password);
|
||||
Map<String, String> tokenMap = new HashMap<>();
|
||||
tokenMap.put("token", token);
|
||||
return R.success(tokenMap);
|
||||
} catch (BadCredentialsException e) {
|
||||
return R.fail("用户名或密码错误");
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "删除当前登录的用户")
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package com.test.bijihoudaun.interceptor;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.test.bijihoudaun.common.response.R;
|
||||
import com.test.bijihoudaun.common.response.ResultCode;
|
||||
import com.test.bijihoudaun.util.JwtTokenUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import io.jsonwebtoken.security.SignatureException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
@@ -35,18 +38,33 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
||||
String authHeader = request.getHeader(this.tokenHeader);
|
||||
if (authHeader != null && authHeader.startsWith(this.tokenHead)) {
|
||||
final String authToken = authHeader.substring(this.tokenHead.length());
|
||||
String username = jwtTokenUtil.getUsernameFromToken(authToken);
|
||||
try {
|
||||
String username = jwtTokenUtil.getUsernameFromToken(authToken);
|
||||
|
||||
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
|
||||
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
|
||||
|
||||
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
||||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
||||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
}
|
||||
} catch (ExpiredJwtException e) {
|
||||
sendErrorResponse(response, ResultCode.TOKEN_EXPIRED);
|
||||
return;
|
||||
} catch (SignatureException e) {
|
||||
sendErrorResponse(response, ResultCode.TOKEN_INVALID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private void sendErrorResponse(HttpServletResponse response, ResultCode resultCode) throws IOException {
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
response.getWriter().write(mapper.writeValueAsString(R.fail(resultCode)));
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import com.test.bijihoudaun.util.JwtTokenUtil;
|
||||
import com.test.bijihoudaun.util.PasswordUtils;
|
||||
import com.test.bijihoudaun.util.UuidV7;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
@@ -69,7 +70,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
|
||||
public String login(String username, String password) {
|
||||
UserDetails userDetails = loadUserByUsername(username);
|
||||
if (!PasswordUtils.verify(password, userDetails.getPassword())) {
|
||||
throw new RuntimeException("密码错误");
|
||||
throw new BadCredentialsException("用户名或密码错误");
|
||||
}
|
||||
return jwtTokenUtil.generateToken(userDetails);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user