feat(all): 修复了鉴权系统无法判断权限的bug

This commit is contained in:
wzp 2024-04-09 17:57:46 +08:00
parent db36ed3fb0
commit 822286ce73
13 changed files with 125 additions and 58 deletions

View File

@ -6,5 +6,5 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuthorizationRequired {
int requiredPermissionId() default -1;
}

View File

@ -0,0 +1,73 @@
package org.mmga.clubs.configuration;
import com.alibaba.fastjson2.JSON;
import com.auth0.jwt.exceptions.JWTVerificationException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.mmga.clubs.annotations.AuthorizationRequired;
import org.mmga.clubs.entities.BaseResponse;
import org.mmga.clubs.service.UserService;
import org.mmga.clubs.utils.JwtUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@Configuration
@Slf4j
public class AuthorizationConfiguration implements HandlerInterceptor, WebMvcConfigurer{
private final JwtUtils jwtUtils;
private final UserService userService;
public AuthorizationConfiguration(JwtUtils jwtUtils, UserService userService){
this.jwtUtils = jwtUtils;
this.userService = userService;
}
@Override
public boolean preHandle(@NonNull HttpServletRequest request,@NonNull HttpServletResponse response,@NonNull Object handler) throws Exception {
if (handler instanceof HandlerMethod handlerMethod){
request.setAttribute("user", -1);
String authorization = request.getHeader("Authorization");
Integer userId;
AuthorizationRequired authorizationRequired = handlerMethod.getMethodAnnotation(AuthorizationRequired.class);
try{
userId = jwtUtils.verifyToken(authorization);
request.setAttribute("user", userId);
if (authorizationRequired != null){
int permissionId = authorizationRequired.requiredPermissionId();
if (permissionId != -1){
if (!userService.userHasPermission(userId, permissionId)) {
writeAuthorizationFailedResponse(response, null);
return false;
}
}
}
}catch (JWTVerificationException e){
if (authorizationRequired != null){
writeAuthorizationFailedResponse(response, e);
return false;
}
}
}
return true;
}
private void writeAuthorizationFailedResponse(HttpServletResponse response, JWTVerificationException e) throws IOException {
log.debug("用户鉴权时出现错误:", e);
ServletOutputStream outputStream = response.getOutputStream();
response.addHeader("Content-Encoding", "UTF-8");
response.addHeader("Content-Type", "application/json; charset=utf-8");
BaseResponse<Object> err = BaseResponse.failed(401, "token错误");
outputStream.write(JSON.toJSONString(err).getBytes(StandardCharsets.UTF_8));
outputStream.close();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(this);
}
}

View File

@ -1,55 +0,0 @@
package org.mmga.clubs.configuration;
import com.alibaba.fastjson2.JSON;
import com.auth0.jwt.exceptions.JWTVerificationException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.mmga.clubs.annotations.AuthorizationRequired;
import org.mmga.clubs.entities.BaseResponse;
import org.mmga.clubs.utils.JwtUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.charset.StandardCharsets;
@Configuration
@Slf4j
public class TokenConfiguration implements HandlerInterceptor, WebMvcConfigurer{
private final JwtUtils jwtUtils;
public TokenConfiguration(JwtUtils jwtUtils){
this.jwtUtils = jwtUtils;
}
@Override
public boolean preHandle(@NonNull HttpServletRequest request,@NonNull HttpServletResponse response,@NonNull Object handler) throws Exception {
if (handler instanceof HandlerMethod handlerMethod){
request.setAttribute("user", -1);
String authorization = request.getHeader("Authorization");
try{
Integer userId = jwtUtils.verifyToken(authorization);
request.setAttribute("user", userId);
}catch (JWTVerificationException e){
if (handlerMethod.hasMethodAnnotation(AuthorizationRequired.class)) {
log.debug("用户鉴权时出现错误:", e);
ServletOutputStream outputStream = response.getOutputStream();
response.addHeader("Content-Encoding", "UTF-8");
response.addHeader("Content-Type", "application/json; charset=utf-8");
BaseResponse<Object> err = BaseResponse.failed(401, "token错误");
outputStream.write(JSON.toJSONString(err).getBytes(StandardCharsets.UTF_8));
outputStream.close();
return false;
}
}
}
return true;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(this);
}
}

View File

@ -5,7 +5,9 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.mmga.clubs.annotations.AuthorizationRequired;
import org.mmga.clubs.entities.BaseResponse;
import org.mmga.clubs.entities.Pager;
import org.mmga.clubs.entities.user.User;
import org.mmga.clubs.entities.user.UserLoginVo;
import org.mmga.clubs.entities.user.UserRegVo;
@ -39,4 +41,10 @@ public class UserController {
public BaseResponse<User> getUserInfo(@RequestAttribute("user") int userId){
return service.getUserInfo(userId);
}
@GetMapping("/all")
@Operation(description = "获取所有用户信息(分页)")
@AuthorizationRequired(requiredPermissionId = 4)
public BaseResponse<Pager<User>> getAllUserInfo(@RequestParam("num") int num, @RequestParam("page") int page){
return service.getAllUserInfo(num, page);
}
}

View File

@ -9,4 +9,5 @@ import java.util.List;
@Mapper
public interface AuthPermissionDao {
List<PermissionVo> getAllPermissionByAuthId(int authId);
int countAuthPermission(int authId, int permissionId);
}

View File

@ -4,10 +4,15 @@ import org.apache.ibatis.annotations.Mapper;
import org.mmga.clubs.entities.user.UserRegResponseVo;
import org.mmga.clubs.entities.user.UserVo;
import java.util.List;
@Mapper
public interface UserDao {
UserVo getUser(String username, String password);
void addUser(UserRegResponseVo userVo);
int countUser(String username);
UserVo getUserById(int id);
int getUserAuthId(int id);
long queryTotalUserCount();
List<UserVo> getUser(int lastId, int count);
}

View File

@ -16,7 +16,7 @@ public class BaseResponse<T> {
private final Date time;
@Schema(description = "返回数据")
private T data;
private BaseResponse(int code, String msg, T data){
protected BaseResponse(int code, String msg, T data){
this.code = code;
this.msg = msg;
this.data = data;

View File

@ -0,0 +1,9 @@
package org.mmga.clubs.entities;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
@Schema(description = "分页数据")
public record Pager<T>(@Schema(description = "总数据") long total,@Schema(description = "当前页面数据") List<T> data) {
}

View File

@ -29,4 +29,8 @@ public class AuthService {
List<Permission> permissions = permissionVos.stream().map(permissionService::packagePermission).toList();
return new Auth(authVo.id(), authVo.name(), permissions);
}
public boolean authHasPermission(int authId, int permissionId) {
return authPermissionDao.countAuthPermission(authId, permissionId) > 0;
}
}

View File

@ -4,11 +4,14 @@ import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.codec.digest.DigestUtils;
import org.mmga.clubs.dao.UserDao;
import org.mmga.clubs.entities.BaseResponse;
import org.mmga.clubs.entities.Pager;
import org.mmga.clubs.entities.user.*;
import org.mmga.clubs.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
private final UserDao userDao;
@ -71,4 +74,15 @@ public class UserService {
}
return BaseResponse.success(getUserById(userId));
}
public boolean userHasPermission(int userId, int permissionId){
return authService.authHasPermission(userDao.getUserAuthId(userId), permissionId);
}
public BaseResponse<Pager<User>> getAllUserInfo(int num, int page) {
long totalCount = userDao.queryTotalUserCount();
List<UserVo> user = userDao.getUser((page - 1) * num, num);
List<User> list = user.stream().map(this::packageUser).toList();
Pager<User> userPager = new Pager<>(totalCount, list);
return BaseResponse.success(userPager);
}
}

View File

@ -6,7 +6,6 @@ import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.mmga.clubs.entities.user.User;
import org.mmga.clubs.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

View File

@ -6,4 +6,7 @@
<select id="getAllPermissionByAuthId" resultType="org.mmga.clubs.entities.permission.PermissionVo">
select `permission`.* from `auth_permission` left join `permission` on `auth_permission`.`permission_id` = `permission`.`id` where `auth_id` = #{authId};
</select>
<select id="countAuthPermission" resultType="java.lang.Integer">
select count(*) from `auth_permission` where `auth_id` = #{authId} and `permission_id` = #{permissionId};
</select>
</mapper>

View File

@ -15,4 +15,10 @@
<select id="getUserById" resultType="org.mmga.clubs.entities.user.UserVo">
select * from `user` where `id` = #{id};
</select>
<select id="getUserAuthId" resultType="java.lang.Integer">
select `auth` from `user` where `id` = #{id};
</select>
<select id="queryTotalUserCount" resultType="java.lang.Long">
select count(*) from `user`;
</select>
</mapper>