💬 修改model注释名称

This commit is contained in:
bunny 2025-07-20 13:50:54 +08:00
parent 73f6a682fe
commit eef46f8164
74 changed files with 1073 additions and 200 deletions

View File

@ -5,6 +5,9 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ -15,6 +18,8 @@ public class Result<T> {
private String message;
// 返回数据
private T data;
// 权限范围
private List<String> auths;
/**
* 自定义返回体
@ -28,17 +33,60 @@ public class Result<T> {
return result;
}
/**
* 自定义返回体
*
* @param data 返回体
* @param auths 权限范围
* @return Result<T>
*/
protected static <T> Result<T> build(T data, List<String> auths) {
Result<T> result = new Result<>();
result.setData(data);
result.setAuths(auths);
return result;
}
/**
* 自定义返回体使用ResultCodeEnum构建
*
* @param data 返回体
* @param codeEnum 返回状态码
* @return {@link Result<T>}
*/
public static <T> Result<T> build(T data, ResultCodeEnum codeEnum) {
Result<T> result = build(data);
result.setCode(codeEnum.getCode());
result.setMessage(codeEnum.getMessage());
return result;
}
/**
* 自定义返回体使用ResultCodeEnum构建
*
* @param data 返回体
* @param codeEnum 返回状态码
* @return {@link Result<T>}
*/
public static <T> Result<T> build(T data, List<String> auths, ResultCodeEnum codeEnum) {
Result<T> result = build(data);
result.setCode(codeEnum.getCode());
result.setMessage(codeEnum.getMessage());
result.setAuths(auths);
return result;
}
/**
* 自定义返回体使用ResultCodeEnum构建
*
* @param body 返回体
* @param codeEnum 返回状态码
* @return Result<T>
*/
public static <T> Result<T> build(T body, ResultCodeEnum codeEnum) {
Result<T> result = build(body);
public static <T> Result<T> build(List<String> auths, ResultCodeEnum codeEnum) {
Result<T> result = build(null);
result.setCode(codeEnum.getCode());
result.setMessage(codeEnum.getMessage());
result.setAuths(auths);
return result;
}
@ -48,13 +96,15 @@ public class Result<T> {
* @param body 返回体
* @param code 返回状态码
* @param message 返回消息
* @return Result<T>
* @param auths 权限范围
* @return {@link Result<T>}
*/
public static <T> Result<T> build(T body, Integer code, String message) {
public static <T> Result<T> build(T body, Integer code, String message, List<String> auths) {
Result<T> result = build(body);
result.setCode(code);
result.setMessage(message);
result.setData(null);
result.setAuths(auths);
return result;
}
@ -76,6 +126,16 @@ public class Result<T> {
return build(data, ResultCodeEnum.SUCCESS);
}
/**
* 操作成功
*
* @param data baseCategory1List
* @param auths 权限范围
*/
public static <T> Result<T> success(T data, List<String> auths) {
return build(data, auths, ResultCodeEnum.SUCCESS);
}
/**
* 操作成功-状态码
*
@ -86,13 +146,32 @@ public class Result<T> {
}
/**
* 操作成功-自定义返回数据和状态码
* 操作成功-状态码
*
* @param data 返回体
* @param codeEnum 状态码
*/
public static <T> Result<T> success(T data, ResultCodeEnum codeEnum) {
return build(data, codeEnum);
return success(data, new ArrayList<>(), codeEnum);
}
/**
* 操作成功-状态码
*
* @param codeEnum 状态码
*/
public static <T> Result<T> success(List<String> auths, ResultCodeEnum codeEnum) {
return build(null, auths, codeEnum);
}
/**
* 操作成功-自定义返回数据和状态码
*
* @param data 返回体
* @param auths 权限范围
* @param codeEnum 状态码
*/
public static <T> Result<T> success(T data, List<String> auths, ResultCodeEnum codeEnum) {
return build(data, auths, codeEnum);
}
/**
@ -102,7 +181,7 @@ public class Result<T> {
* @param message 错误信息
*/
public static <T> Result<T> success(T data, String message) {
return build(data, 200, message);
return build(data, 200, message, new ArrayList<>());
}
/**
@ -113,7 +192,7 @@ public class Result<T> {
* @param message 错误信息
*/
public static <T> Result<T> success(T data, Integer code, String message) {
return build(data, code, message);
return build(data, code, message, new ArrayList<>());
}
/**
@ -159,7 +238,7 @@ public class Result<T> {
* @param message 错误信息
*/
public static <T> Result<T> error(T data, Integer code, String message) {
return build(data, code, message);
return build(data, code, message, new ArrayList<>());
}
/**
@ -169,6 +248,6 @@ public class Result<T> {
* @param message 错误信息
*/
public static <T> Result<T> error(T data, String message) {
return build(null, 500, message);
return build(null, 500, message, new ArrayList<>());
}
}

View File

@ -0,0 +1,59 @@
package com.auth.dao.base.entity.base;
import com.auth.common.model.common.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@Getter
@Setter
@Accessors(chain = true)
@TableName("sys_auth_log")
@Schema(name = "AuthLog-系统授权日志实体类", title = "系统授权日志", description = "系统授权日志的实体类对象")
public class AuthLogEntity extends BaseEntity {
@Schema(name = "eventType", title = "事件类型(GRANTED=授权成功,DENIED=授权拒绝)")
private String eventType;
@Schema(name = "username", title = "用户名")
private String username;
@Schema(name = "userId", title = "用户ID")
private Long userId;
@Schema(name = "requestIp", title = "请求IP")
private String requestIp;
@Schema(name = "requestMethod", title = "请求方法(GET,POST等)")
private String requestMethod;
@Schema(name = "requestUri", title = "请求URI")
private String requestUri;
@Schema(name = "className", title = "类名")
private String className;
@Schema(name = "methodName", title = "方法名")
private String methodName;
@Schema(name = "methodParams", title = "方法参数(JSON格式)")
private String methodParams;
@Schema(name = "requiredAuthority", title = "所需权限达式")
private String requiredAuthority;
@Schema(name = "userAuthorities", title = "用户拥有的权限(JSON格式)")
private String userAuthorities;
@Schema(name = "decisionReason", title = "决策原因")
private String decisionReason;
@Schema(name = "exceptionMessage", title = "异常信息")
private String exceptionMessage;
@Schema(name = "isDeleted", title = "删除标志(0=未删除 1=已删除)")
private Boolean isDeleted;
}

View File

@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
@TableName("sys_dept")
@Schema(name = "Dept对象", title = "部门", description = "部门的实体类对象")
@Schema(name = "Dept-部门实体类", title = "部门", description = "部门的实体类对象")
public class DeptEntity extends BaseEntity {
@Schema(name = "parentId", title = "父级id")

View File

@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
@TableName("sys_dict")
@Schema(name = "Dict对象", title = "系统数据字典", description = "系统数据字典的实体类对象")
@Schema(name = "Dict-系统数据字典实体类", title = "系统数据字典", description = "系统数据字典的实体类对象")
public class DictEntity extends BaseEntity {
@Schema(name = "dictType", title = "字典类型")

View File

@ -13,7 +13,7 @@ import java.time.LocalDateTime;
@Setter
@Accessors(chain = true)
@TableName("sys_email_config")
@Schema(name = "EmailConfig对象", title = "系统邮件服务器配置", description = "系统邮件服务器配置的实体类对象")
@Schema(name = "EmailConfig-系统邮件服务器配置实体类对象", title = "系统邮件服务器配置", description = "系统邮件服务器配置的实体类对象")
public class EmailConfigEntity extends BaseEntity {
@Schema(name = "configName", title = "配置名称")

View File

@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
@TableName("sys_email_template")
@Schema(name = "EmailTemplate对象", title = "邮件模板", description = "邮件模板的实体类对象")
@Schema(name = "EmailTemplate-邮件模板实体类", title = "邮件模板", description = "邮件模板的实体类对象")
public class EmailTemplateEntity extends BaseEntity {
@Schema(name = "templateName", title = "模板名称")

View File

@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
@TableName("sys_file")
@Schema(name = "File对象", title = "系统文件存储", description = "系统文件存储的实体类对象")
@Schema(name = "File-系统文件存储实体类", title = "系统文件存储", description = "系统文件存储的实体类对象")
public class FileEntity extends BaseEntity {
@Schema(name = "fileUid", title = "文件唯一标识(可用于外部引用)")

View File

@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
@TableName("sys_login_log")
@Schema(name = "LoginLog对象", title = "系统用户登录日志", description = "系统用户登录日志的实体类对象")
@Schema(name = "LoginLog-系统用户登录日志实体类", title = "系统用户登录日志", description = "系统用户登录日志的实体类对象")
public class LoginLogEntity extends BaseEntity {
@Schema(name = "userId", title = "用户ID")

View File

@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
@TableName("sys_menu")
@Schema(name = "Menu对象", title = "系统菜单权限", description = "系统菜单权限的实体类对象")
@Schema(name = "Menu-系统菜单权限实体类", title = "系统菜单权限", description = "系统菜单权限的实体类对象")
public class MenuEntity extends BaseEntity {
@Schema(name = "parentId", title = "父菜单ID(0表示一级菜单)")

View File

@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
@TableName("sys_menu_role")
@Schema(name = "MenuRole对象", title = "系统菜单角色关联", description = "系统菜单角色关联的实体类对象")
@Schema(name = "MenuRole-系统菜单角色关联实体类", title = "系统菜单角色关联", description = "系统菜单角色关联的实体类对象")
public class MenuRoleEntity extends BaseEntity {
@Schema(name = "roleId", title = "角色ID")

View File

@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
@TableName("sys_operation_log")
@Schema(name = "OperationLog对象", title = "系统操作日志", description = "系统操作日志的实体类对象")
@Schema(name = "OperationLog-系统操作日志实体类", title = "系统操作日志", description = "系统操作日志的实体类对象")
public class OperationLogEntity extends BaseEntity {
@Schema(name = "module", title = "操作模块")

View File

@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
@TableName("sys_permission")
@Schema(name = "Permission对象", title = "系统权限", description = "系统权限的实体类对象")
@Schema(name = "Permission-系统权限实体类", title = "系统权限", description = "系统权限的实体类对象")
public class PermissionEntity extends BaseEntity {
@Schema(name = "parentId", title = "父级id")

View File

@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
@TableName("sys_role_data_scope")
@Schema(name = "RoleDataScope对象", title = "系统角色数据权限范围", description = "系统角色数据权限范围的实体类对象")
@Schema(name = "RoleDataScope-系统角色数据权限范围实体类", title = "系统角色数据权限范围", description = "系统角色数据权限范围的实体类对象")
public class RoleDataScopeEntity extends BaseEntity {
@Schema(name = "roleId", title = "角色ID")

View File

@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
@TableName("sys_role")
@Schema(name = "Role对象", title = "系统角色", description = "系统角色的实体类对象")
@Schema(name = "Role-系统角色实体类", title = "系统角色", description = "系统角色的实体类对象")
public class RoleEntity extends BaseEntity {
@Schema(name = "roleCode", title = "角色代码")

View File

@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
@TableName("sys_role_permission")
@Schema(name = "RolePermission对象", title = "系统角色权限", description = "系统角色权限的实体类对象")
@Schema(name = "RolePermission-系统角色权限实体类", title = "系统角色权限", description = "系统角色权限的实体类对象")
public class RolePermissionEntity extends BaseEntity {
@Schema(name = "roleId", title = "角色id")

View File

@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
@TableName("sys_user_dept")
@Schema(name = "UserDept对象", title = "部门用户关系", description = "部门用户关系的实体类对象")
@Schema(name = "UserDept-部门用户关系实体类", title = "部门用户关系", description = "部门用户关系的实体类对象")
public class UserDeptEntity extends BaseEntity {
@Schema(name = "userId", title = "用户id")

View File

@ -20,7 +20,7 @@ import java.util.Set;
@Setter
@Accessors(chain = true)
@TableName("sys_user")
@Schema(name = "User对象", title = "用户信息", description = "用户信息的实体类对象")
@Schema(name = "User-用户信息实体类", title = "用户信息", description = "用户信息的实体类对象")
public class UserEntity implements UserDetails, CredentialsContainer {
@Schema(name = "id", title = "唯一标识")

View File

@ -11,7 +11,7 @@ import lombok.experimental.Accessors;
@Setter
@Accessors(chain = true)
@TableName("sys_user_role")
@Schema(name = "UserRole对象", title = "系统用户角色关系", description = "系统用户角色关系的实体类对象")
@Schema(name = "UserRole系统用户角色关系实体类", title = "系统用户角色关系", description = "系统用户角色关系的实体类对象")
public class UserRoleEntity extends BaseEntity {
@Schema(name = "userId", title = "用户id")

View File

@ -0,0 +1,33 @@
package com.auth.dao.base.mapper.v1;
import com.auth.dao.base.entity.base.AuthLogEntity;
import com.auth.model.base.dto.AuthLogDto;
import com.auth.model.base.vo.AuthLogVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* <p>
* 系统授权日志表 Mapper 接口
* </p>
*
* @author AuthoritySystem
* @since 2025-07-19 14:26:58
*/
@Mapper
public interface AuthLogMapper extends BaseMapper<AuthLogEntity> {
/**
* 分页查询系统授权日志表内容
*
* @param pageParams 系统授权日志表分页参数
* @param dto 系统授权日志表查询表单
* @return 系统授权日志表分页结果
*/
IPage<AuthLogVo> selectListByPage(@Param("page") Page<AuthLogEntity> pageParams, @Param("dto") AuthLogDto dto);
}

View File

@ -1 +0,0 @@
package com.auth.dao.base;

View File

@ -0,0 +1,89 @@
<?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="com.auth.dao.base.mapper.v1.AuthLogMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.auth.dao.base.entity.base.AuthLogEntity">
<id column="id" property="id"/>
<id column="event_type" property="eventType"/>
<id column="username" property="username"/>
<id column="user_id" property="userId"/>
<id column="request_ip" property="requestIp"/>
<id column="request_method" property="requestMethod"/>
<id column="request_uri" property="requestUri"/>
<id column="class_name" property="className"/>
<id column="method_name" property="methodName"/>
<id column="method_params" property="methodParams"/>
<id column="required_authority" property="requiredAuthority"/>
<id column="user_authorities" property="userAuthorities"/>
<id column="decision_reason" property="decisionReason"/>
<id column="exception_message" property="exceptionMessage"/>
<id column="is_deleted" property="isDeleted"/>
<id column="create_time" property="createTime"/>
<id column="update_time" property="updateTime"/>
<id column="create_user" property="createUser"/>
<id column="update_user" property="updateUser"/>
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, event_type,username,user_id,request_ip,request_method,request_uri,class_name,method_name,method_params,required_authority,user_authorities,decision_reason,exception_message,is_deleted, create_time, update_time, create_user, update_user
</sql>
<!-- 分页查询系统授权日志表内容 -->
<select id="selectListByPage" resultType="com.auth.model.base.vo.AuthLogVo">
select
base.*,
create_user.username as create_username,
update_user.username as update_username
from sys_auth_log base
left join sys_user create_user on create_user.id = base.create_user
left join sys_user update_user on update_user.id = base.update_user
<where>
base.is_deleted = 0
<if test="dto.eventType != null and dto.eventType != ''">
and base.event_type like CONCAT('%',#{dto.eventType},'%')
</if>
<if test="dto.username != null and dto.username != ''">
and base.username like CONCAT('%',#{dto.username},'%')
</if>
<if test="dto.userId != null and dto.userId != ''">
and base.user_id like CONCAT('%',#{dto.userId},'%')
</if>
<if test="dto.requestIp != null and dto.requestIp != ''">
and base.request_ip like CONCAT('%',#{dto.requestIp},'%')
</if>
<if test="dto.requestMethod != null and dto.requestMethod != ''">
and base.request_method like CONCAT('%',#{dto.requestMethod},'%')
</if>
<if test="dto.requestUri != null and dto.requestUri != ''">
and base.request_uri like CONCAT('%',#{dto.requestUri},'%')
</if>
<if test="dto.className != null and dto.className != ''">
and base.class_name like CONCAT('%',#{dto.className},'%')
</if>
<if test="dto.methodName != null and dto.methodName != ''">
and base.method_name like CONCAT('%',#{dto.methodName},'%')
</if>
<if test="dto.methodParams != null and dto.methodParams != ''">
and base.method_params like CONCAT('%',#{dto.methodParams},'%')
</if>
<if test="dto.requiredAuthority != null and dto.requiredAuthority != ''">
and base.required_authority like CONCAT('%',#{dto.requiredAuthority},'%')
</if>
<if test="dto.userAuthorities != null and dto.userAuthorities != ''">
and base.user_authorities like CONCAT('%',#{dto.userAuthorities},'%')
</if>
<if test="dto.decisionReason != null and dto.decisionReason != ''">
and base.decision_reason like CONCAT('%',#{dto.decisionReason},'%')
</if>
<if test="dto.exceptionMessage != null and dto.exceptionMessage != ''">
and base.exception_message like CONCAT('%',#{dto.exceptionMessage},'%')
</if>
<if test="dto.isDeleted != null and dto.isDeleted != ''">
and base.is_deleted like CONCAT('%',#{dto.isDeleted},'%')
</if>
</where>
</select>
</mapper>

View File

@ -0,0 +1,52 @@
package com.auth.model.base.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "AuthLogDTO-系统授权日志", title = "系统授权日志", description = "系统授权日志的DTO对象")
public class AuthLogDto {
@Schema(name = "eventType", title = "事件类型(GRANTED=授权成功,DENIED=授权拒绝)")
private String eventType;
@Schema(name = "username", title = "用户名")
private String username;
@Schema(name = "userId", title = "用户ID")
private Long userId;
@Schema(name = "requestIp", title = "请求IP")
private String requestIp;
@Schema(name = "requestMethod", title = "请求方法(GET,POST等)")
private String requestMethod;
@Schema(name = "requestUri", title = "请求URI")
private String requestUri;
@Schema(name = "className", title = "类名")
private String className;
@Schema(name = "methodName", title = "方法名")
private String methodName;
@Schema(name = "methodParams", title = "方法参数(JSON格式)")
private String methodParams;
@Schema(name = "requiredAuthority", title = "所需权限表达式")
private String requiredAuthority;
@Schema(name = "userAuthorities", title = "用户拥有的权限(JSON格式)")
private String userAuthorities;
@Schema(name = "decisionReason", title = "决策原因")
private String decisionReason;
@Schema(name = "exceptionMessage", title = "异常信息")
private String exceptionMessage;
@Schema(name = "isDeleted", title = "删除标志(0=未删除 1=已删除)")
private Boolean isDeleted;
}

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "DeptDTO对象", title = "部门", description = "部门的DTO对象")
@Schema(name = "DeptDTO-部门传输类", title = "部门", description = "部门的DTO对象")
public class DeptDto {
@Schema(name = "parentId", title = "父级id")

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "DictDTO对象", title = "系统数据字典", description = "系统数据字典的DTO对象")
@Schema(name = "DictDTO-系统数据字典传输", title = "系统数据字典", description = "系统数据字典的DTO对象")
public class DictDto {
@Schema(name = "dictType", title = "字典类型")

View File

@ -12,7 +12,7 @@ import java.time.LocalDateTime;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "EmailConfigDTO对象", title = "系统邮件服务器配置", description = "系统邮件服务器配置的DTO对象")
@Schema(name = "EmailConfigDTO-系统邮件服务器配置传输对象", title = "系统邮件服务器配置", description = "系统邮件服务器配置的DTO对象")
public class EmailConfigDto {
@Schema(name = "configName", title = "配置名称")

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "EmailTemplateDTO对象", title = "邮件模板", description = "邮件模板的DTO对象")
@Schema(name = "EmailTemplateDTO-邮件模板传输对象", title = "邮件模板", description = "邮件模板的DTO对象")
public class EmailTemplateDto {
@Schema(name = "templateName", title = "模板名称")

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "FileDTO对象", title = "系统文件存储", description = "系统文件存储的DTO对象")
@Schema(name = "FileDTO-系统文件存储传输对象", title = "系统文件存储", description = "系统文件存储的DTO对象")
public class FileDto {
@Schema(name = "fileUid", title = "文件唯一标识(可用于外部引用)")

View File

@ -4,7 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(name = "LoginDto", title = "LoginDto登录参数", description = "登录请求参数")
@Schema(name = "LoginDTO-登录表单", title = "登录表单", description = "登录请求参数")
public class LoginDto {
@Schema(name = "type", description = "登录类型")

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "LoginLogDTO对象", title = "系统用户登录日志", description = "系统用户登录日志的DTO对象")
@Schema(name = "LoginLogDTO-系统用户登录日志传输对象", title = "系统用户登录日志", description = "系统用户登录日志的DTO对象")
public class LoginLogDto {
@Schema(name = "userId", title = "用户ID")

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "MenuDTO对象", title = "系统菜单权限", description = "系统菜单权限的DTO对象")
@Schema(name = "MenuDTO-系统菜单权限传输对象", title = "系统菜单权限", description = "系统菜单权限的DTO对象")
public class MenuDto {
@Schema(name = "parentId", title = "父菜单ID(0表示一级菜单)")

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "MenuRoleDTO对象", title = "系统菜单角色关联", description = "系统菜单角色关联的DTO对象")
@Schema(name = "MenuRoleDTO-系统菜单角色关联传输对象", title = "系统菜单角色关联", description = "系统菜单角色关联的DTO对象")
public class MenuRoleDto {
@Schema(name = "roleId", title = "角色ID")

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "OperationLogDTO对象", title = "系统操作日志", description = "系统操作日志的DTO对象")
@Schema(name = "OperationLogDTO-系统操作日志传输对象", title = "系统操作日志", description = "系统操作日志的DTO对象")
public class OperationLogDto {
@Schema(name = "module", title = "操作模块")

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "PermissionDTO对象", title = "系统权限", description = "系统权限的DTO对象")
@Schema(name = "PermissionDTO-系统权限传输对象", title = "系统权限", description = "系统权限的DTO对象")
public class PermissionDto {
@Schema(name = "parentId", title = "父级id")

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "RoleDataScopeDTO对象", title = "系统角色数据权限范围", description = "系统角色数据权限范围的DTO对象")
@Schema(name = "RoleDataScopeDTO-系统角色数据权限范围传输对象", title = "系统角色数据权限范围", description = "系统角色数据权限范围的DTO对象")
public class RoleDataScopeDto {
@Schema(name = "roleId", title = "角色ID")

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "RoleDTO对象", title = "系统角色", description = "系统角色的DTO对象")
@Schema(name = "RoleDTO-系统角色传输对象", title = "系统角色", description = "系统角色的DTO对象")
public class RoleDto {
@Schema(name = "roleCode", title = "角色代码")

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "RolePermissionDTO对象", title = "系统角色权限", description = "系统角色权限的DTO对象")
@Schema(name = "RolePermissionDTO-系统角色权限传输对象", title = "系统角色权限", description = "系统角色权限的DTO对象")
public class RolePermissionDto {
@Schema(name = "roleId", title = "角色id")

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "UserDeptDTO对象", title = "部门用户关系", description = "部门用户关系的DTO对象")
@Schema(name = "UserDeptDTO-部门用户关系传输对象", title = "部门用户关系", description = "部门用户关系的DTO对象")
public class UserDeptDto {
@Schema(name = "userId", title = "用户id")

View File

@ -13,7 +13,7 @@ import java.util.Date;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "UserDTO对象", title = "用户信息", description = "用户信息的DTO对象")
@Schema(name = "UserDTO-用户信息传输对象", title = "用户信息", description = "用户信息的DTO对象")
public class UserDto {
@Schema(name = "username", title = "用户名")
@ -31,7 +31,7 @@ public class UserDto {
@Schema(name = "password", title = "密码")
private String password;
@Schema(name = "avatar", title = "")
@Schema(name = "avatar", title = "头像URL")
private String avatar;
@Schema(name = "sex", title = "0:女 1:男")

View File

@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "UserRoleDTO对象", title = "系统用户角色关系", description = "系统用户角色关系的DTO对象")
@Schema(name = "UserRoleDTO-系统用户角色关系传输对象", title = "系统用户角色关系", description = "系统用户角色关系的DTO对象")
public class UserRoleDto {
@Schema(name = "userId", title = "用户id")

View File

@ -0,0 +1,60 @@
package com.auth.model.base.vo;
import com.auth.common.model.common.BaseVo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "AuthLogVO-系统授权日志表返回对象", title = "系统授权日志表", description = "系统授权日志表的VO对象")
public class AuthLogVo extends BaseVo {
@Schema(name = "eventType", title = "事件类型(GRANTED=授权成功,DENIED=授权拒绝)")
private String eventType;
@Schema(name = "username", title = "用户名")
private String username;
@Schema(name = "userId", title = "用户ID")
private Long userId;
@Schema(name = "requestIp", title = "请求IP")
private String requestIp;
@Schema(name = "requestMethod", title = "请求方法(GET,POST等)")
private String requestMethod;
@Schema(name = "requestUri", title = "请求URI")
private String requestUri;
@Schema(name = "className", title = "类名")
private String className;
@Schema(name = "methodName", title = "方法名")
private String methodName;
@Schema(name = "methodParams", title = "方法参数(JSON格式)")
private String methodParams;
@Schema(name = "requiredAuthority", title = "所需权限表达式")
private String requiredAuthority;
@Schema(name = "userAuthorities", title = "用户拥有的权限(JSON格式)")
private String userAuthorities;
@Schema(name = "decisionReason", title = "决策原因")
private String decisionReason;
@Schema(name = "exceptionMessage", title = "异常信息")
private String exceptionMessage;
@Schema(name = "isDeleted", title = "删除标志(0=未删除 1=已删除)")
private Boolean isDeleted;
}

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "DeptVO对象", title = "部门", description = "部门的VO对象")
@Schema(name = "DeptVO-部门返回对象", title = "部门", description = "部门的VO对象")
public class DeptVo {
@Schema(name = "parentId", title = "父级id")

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "DictVO对象", title = "系统数据字典", description = "系统数据字典的VO对象")
@Schema(name = "DictVO-系统数据字典返回对象", title = "系统数据字典", description = "系统数据字典的VO对象")
public class DictVo {
@Schema(name = "dictType", title = "字典类型")

View File

@ -10,7 +10,7 @@ import java.time.LocalDateTime;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "EmailConfigVO对象", title = "系统邮件服务器配置", description = "系统邮件服务器配置的VO对象")
@Schema(name = "EmailConfigVO-系统邮件服务器配置返回对象", title = "系统邮件服务器配置", description = "系统邮件服务器配置的VO对象")
public class EmailConfigVo {
@Schema(name = "configName", title = "配置名称")

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "EmailTemplateVO对象", title = "邮件模板", description = "邮件模板的VO对象")
@Schema(name = "EmailTemplateVO-邮件模板返回对象", title = "邮件模板", description = "邮件模板的VO对象")
public class EmailTemplateVo {
@Schema(name = "templateName", title = "模板名称")

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "FileVO对象", title = "系统文件存储", description = "系统文件存储的VO对象")
@Schema(name = "FileVO-系统文件存储返回对象", title = "系统文件存储", description = "系统文件存储的VO对象")
public class FileVo {
@Schema(name = "fileUid", title = "文件唯一标识(可用于外部引用)")

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "LoginLogVO对象", title = "系统用户登录日志", description = "系统用户登录日志的VO对象")
@Schema(name = "LoginLogVO-系统用户登录日志返回对象", title = "系统用户登录日志", description = "系统用户登录日志的VO对象")
public class LoginLogVo {
@Schema(name = "userId", title = "用户ID")

View File

@ -11,7 +11,7 @@ import lombok.NoArgsConstructor;
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "LoginVo对象", title = "登录成功返回内容", description = "登录成功返回内容")
@Schema(name = "LoginVo-登录成功返回内容返回对象", title = "登录成功返回内容", description = "登录成功返回内容")
public class LoginVo extends BaseVo {
@Schema(name = "nickname", title = "昵称")

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "MenuRoleVO对象", title = "系统菜单角色关联", description = "系统菜单角色关联的VO对象")
@Schema(name = "MenuRoleVO-系统菜单角色关联返回对象", title = "系统菜单角色关联", description = "系统菜单角色关联的VO对象")
public class MenuRoleVo {
@Schema(name = "roleId", title = "角色ID")

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "MenuVO对象", title = "系统菜单权限", description = "系统菜单权限的VO对象")
@Schema(name = "MenuVO-系统菜单权限返回对象", title = "系统菜单权限", description = "系统菜单权限的VO对象")
public class MenuVo {
@Schema(name = "parentId", title = "父菜单ID(0表示一级菜单)")

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "OperationLogVO对象", title = "系统操作日志", description = "系统操作日志的VO对象")
@Schema(name = "OperationLogVO-系统操作日志返回对象", title = "系统操作日志", description = "系统操作日志的VO对象")
public class OperationLogVo {
@Schema(name = "module", title = "操作模块")

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "PermissionVO对象", title = "系统权限", description = "系统权限的VO对象")
@Schema(name = "PermissionVO-系统权限返回对象", title = "系统权限", description = "系统权限的VO对象")
public class PermissionVo {
@Schema(name = "parentId", title = "父级id")

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "RoleDataScopeVO对象", title = "系统角色数据权限范围", description = "系统角色数据权限范围的VO对象")
@Schema(name = "RoleDataScopeVO-系统角色数据权限范围返回对象", title = "系统角色数据权限范围", description = "系统角色数据权限范围的VO对象")
public class RoleDataScopeVo {
@Schema(name = "roleId", title = "角色ID")

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "RolePermissionVO对象", title = "系统角色权限", description = "系统角色权限的VO对象")
@Schema(name = "RolePermissionVO-系统角色权限返回对象", title = "系统角色权限", description = "系统角色权限的VO对象")
public class RolePermissionVo {
@Schema(name = "roleId", title = "角色id")

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "RoleVO对象", title = "系统角色", description = "系统角色的VO对象")
@Schema(name = "RoleVO-系统角色对象", title = "系统角色", description = "系统角色的VO对象")
public class RoleVo {
@Schema(name = "roleCode", title = "角色代码")

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "UserDeptVO对象", title = "部门用户关系", description = "部门用户关系的VO对象")
@Schema(name = "UserDeptVO-部门用户关系返回对象", title = "部门用户关系", description = "部门用户关系的VO对象")
public class UserDeptVo {
@Schema(name = "userId", title = "用户id")

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "UserRoleVO对象", title = "系统用户角色关系", description = "系统用户角色关系的VO对象")
@Schema(name = "UserRoleVO-系统用户角色关系返回对象", title = "系统用户角色关系", description = "系统用户角色关系的VO对象")
public class UserRoleVo {
@Schema(name = "userId", title = "用户id")

View File

@ -11,7 +11,7 @@ import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "UserVO对象", title = "用户信息", description = "用户信息的VO对象")
@Schema(name = "用户信息返回对象", title = "用户信息", description = "用户信息的VO对象")
public class UserVo {
@Schema(name = "username", title = "用户名")
@ -29,7 +29,7 @@ public class UserVo {
@Schema(name = "password", title = "密码")
private String password;
@Schema(name = "avatar", title = "")
@Schema(name = "avatar", title = "头像URL")
private String avatar;
@Schema(name = "sex", title = "0:女 1:男")

View File

@ -0,0 +1,50 @@
package com.auth.module.security.annotation;
import com.auth.module.security.config.properties.SecurityConfigProperties;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
@Component("auth")
@RequiredArgsConstructor
public class AuthorizationLogic {
private final SecurityConfigProperties securityConfigProperties;
/**
* 基本权限检查
*/
public boolean decide(String requiredAuthority) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return false;
}
// 检查用户是否有指定权限或是admin
boolean baseAuthority = authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.anyMatch(auth -> auth.equals(requiredAuthority));
return baseAuthority || isAdmin(authentication);
}
/**
* 检查是否是管理员
*/
public boolean isAdmin() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return authentication != null && isAdmin(authentication);
}
private boolean isAdmin(Authentication authentication) {
return securityConfigProperties.getAdminAuthorities().stream()
.anyMatch(auth -> authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.anyMatch(ga -> ga.equals(auth)));
}
}

View File

@ -1,14 +0,0 @@
package com.auth.module.security.annotation.programmatically;
import org.springframework.stereotype.Component;
@Component("auth")
public class AuthorizationLogic {
public boolean decide(String name) {
// 直接使用name的实现
// System.out.println(name);
return name.equalsIgnoreCase("user");
}
}

View File

@ -1,10 +1,24 @@
package com.auth.module.security.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
@Configuration
// @EnableMethodSecurity(prePostEnabled = false)
public class AuthorizationManagerConfiguration {
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
// 可选配置---移除 ROLE_ 前缀
// handler.setDefaultRolePrefix("");
return handler;
}
// @Bean
// @Role(BeanDefinition.ROLE_INFRASTRUCTURE)

View File

@ -1,6 +1,7 @@
package com.auth.module.security.config;
import com.auth.module.security.config.properties.SecurityConfigProperties;
import com.auth.module.security.filter.JwtAuthenticationFilter;
import com.auth.module.security.handler.SecurityAccessDeniedHandler;
import com.auth.module.security.handler.SecurityAuthenticationEntryPoint;
@ -15,7 +16,6 @@ import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import java.util.List;
@Configuration
@EnableWebSecurity
@ -23,16 +23,15 @@ import java.util.List;
@RequiredArgsConstructor
public class SecurityWebConfiguration {
public static List<String> securedPaths = List.of("/api/**");
public static List<String> noAuthPaths = List.of("/*/login");
private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final SecurityConfigProperties pathsProperties;
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// 前端段分离不需要---禁用明文验证
.httpBasic(AbstractHttpConfigurer::disable)
// .httpBasic(AbstractHttpConfigurer::disable)
// 前端段分离不需要---禁用默认登录页
.formLogin(AbstractHttpConfigurer::disable)
// 前端段分离不需要---禁用退出页
@ -46,18 +45,19 @@ public class SecurityWebConfiguration {
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
// 如果要对部分接口做登录校验 或者 项目中需要使用粗粒度的 校验
.authorizeHttpRequests(authorizeRequests ->
// 访问路径为 /api 时需要进行认证
authorizeRequests
// 不认证登录接口
.requestMatchers(noAuthPaths.toArray(String[]::new)).permitAll()
.requestMatchers(pathsProperties.noAuthPaths.toArray(String[]::new)).permitAll()
// 只认证 securedPaths 下的所有接口
// =======================================================================
// 也可以在这里写多参数传入"/api/**","/admin/**"
// 但是在 Spring过滤器中如果要放行不需要认证请求但是需要认证的接口必需要携带token
// 做法是在这里定义要认证的接口如果要做成动态可以放到数据库
// =======================================================================
.requestMatchers(securedPaths.toArray(String[]::new)).authenticated()
.requestMatchers(pathsProperties.securedPaths.toArray(String[]::new)).authenticated()
// 其余请求都放行
.anyRequest().permitAll()
)
@ -67,7 +67,7 @@ public class SecurityWebConfiguration {
// 没有权限访问
exception.accessDeniedHandler(new SecurityAccessDeniedHandler());
})
.addFilterAfter(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
;
return http.build();

View File

@ -1,4 +1,4 @@
package com.auth.module.security.password;
package com.auth.module.security.config.password;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.DigestUtils;

View File

@ -0,0 +1,27 @@
package com.auth.module.security.config.properties;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "security-path")
@Schema(name = "SecurityPathsProperties对象", description = "路径忽略和认证")
public class SecurityConfigProperties {
@Schema(name = "noAuthPaths", description = "不用认证的路径")
public List<String> noAuthPaths;
@Schema(name = "securedPaths", description = "需要认证的路径")
public List<String> securedPaths;
@Schema(name = "允许的角色或权限", description = "允许的角色或权限")
public List<String> adminAuthorities;
}

View File

@ -1,5 +1,11 @@
package com.auth.module.security.event;
import com.alibaba.fastjson2.JSON;
import com.auth.common.context.BaseContext;
import com.auth.dao.base.entity.base.AuthLogEntity;
import com.auth.dao.base.mapper.v1.AuthLogMapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.context.event.EventListener;
@ -8,14 +14,18 @@ import org.springframework.security.authorization.event.AuthorizationDeniedEvent
import org.springframework.security.authorization.event.AuthorizationGrantedEvent;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.lang.reflect.Method;
import java.util.Arrays;
@Slf4j
@Component
@RequiredArgsConstructor
public class AuthenticationEvents {
private final AuthLogMapper authLogMapper;
/**
* 监听拒绝授权内容
*
@ -24,29 +34,48 @@ public class AuthenticationEvents {
@EventListener
public void onFailure(AuthorizationDeniedEvent<MethodInvocation> failure) {
try {
// getSource getObject意思一样一种是传入泛型自动转换一种是要手动转换
Object source = failure.getSource();
// 直接获取泛型对象
// 当前执行的方法
MethodInvocation methodInvocation = failure.getObject();
// 方法名称
Method method = methodInvocation.getMethod();
// 方法参数
Object[] args = methodInvocation.getArguments();
log.warn("方法调用被拒绝: {}.{}, 参数: {}",
method.getDeclaringClass().getSimpleName(),
method.getName(),
Arrays.toString(args));
// 这里面的信息和接口 /api/security/current-user 内容一样
// 用户身份
Authentication authentication = failure.getAuthentication().get();
// 用户名
String username = authentication.getName();
// 决策结果
AuthorizationDecision decision = failure.getAuthorizationDecision();
AuthorizationDecision authorizationDecision = failure.getAuthorizationDecision();
// ExpressionAuthorizationDecision [granted=false, expressionAttribute=hasAuthority('ADMIN')]
System.out.println(authorizationDecision);
// 获取请求上下文信息
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
AuthLogEntity authLog = new AuthLogEntity();
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
authLog.setRequestIp(request.getRemoteAddr());
authLog.setRequestMethod(request.getMethod());
authLog.setRequestUri(request.getRequestURI());
}
// 构建日志实体
authLog.setEventType("DENIED");
authLog.setUsername(username);
// 需要实现获取用户ID的方法
authLog.setUserId(BaseContext.getUserId());
authLog.setClassName(method.getDeclaringClass().getName());
authLog.setMethodName(method.getName());
authLog.setMethodParams(JSON.toJSONString(args));
authLog.setRequiredAuthority(decision.toString());
authLog.setUserAuthorities(JSON.toJSONString(authentication.getAuthorities()));
authLog.setCreateUser(BaseContext.getUserId());
// 保存到数据库
authLogMapper.insert(authLog);
log.warn("授权失败 - 用户: {}, 权限: {}", authentication.getName(), authorizationDecision);
} catch (Exception e) {
log.info(e.getMessage());
log.error("记录授权失败日志异常", e);
}
}

View File

@ -1,48 +1,67 @@
package com.auth.module.security.manger;
import com.auth.common.model.common.result.Result;
import com.auth.module.security.config.properties.SecurityConfigProperties;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.authorization.method.MethodInvocationResult;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.function.Supplier;
/**
* 处理方法调用后的授权检查
* check()方法接收的是MethodInvocationResult对象包含已执行方法的结果
* 用于决定是否允许返回某个方法的结果(后置过滤)
* 这是Spring Security较新的"后置授权"功能
*/
// @Component
// public class PostAuthorizationManager implements AuthorizationManager<MethodInvocationResult> {
//
// /**
// * 这里两个实现方法按照Security官方要求进行实现
// * <h4>类说明</h4>
// * 下面的实现是对方法执行前进行权限校验的判断
// * <pre>
// * <code>AuthorizationManager &ltMethodInvocation></code>
// * </pre>
// * 下面的这个是对方法执行后对权限的判断
// * <pre>
// * <code>AuthorizationManager &ltMethodInvocationResult></code>
// * </pre>
// *
// * <h4>注意事项</h4>
// * 将上述两个方法按照自定义的方式进行实现后还需要禁用默认的
// * <pre>
// * &#064;Configuration
// * &#064;EnableMethodSecurity(prePostEnabled = false)
// * class MethodSecurityConfig {
// * &#064;Bean
// * &#064;Role(BeanDefinition.ROLE_INFRASTRUCTURE)
// * Advisor preAuthorize(MyAuthorizationManager manager) {
// * return AuthorizationManagerBeforeMethodInterceptor.preAuthorize(manager);
// * }
// *
// * &#064;Bean
// * &#064;Role(BeanDefinition.ROLE_INFRASTRUCTURE)
// * Advisor postAuthorize(MyAuthorizationManager manager) {
// * return AuthorizationManagerAfterMethodInterceptor.postAuthorize(manager);
// * }
// * }
// * </pre>
// */
// @Override
// public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocationResult invocation) {
// return new AuthorizationDecision(true);
// }
// }
@Component
@RequiredArgsConstructor
public class PostAuthorizationManager implements AuthorizationManager<MethodInvocationResult> {
private final SecurityConfigProperties securityConfigProperties;
@Override
public AuthorizationDecision check(Supplier<Authentication> authenticationSupplier, MethodInvocationResult methodInvocationResult) {
Authentication authentication = authenticationSupplier.get();
// 如果方法有 @PreAuthorize 注解会先到这里
if (authentication == null || !authentication.isAuthenticated()) {
return new AuthorizationDecision(false);
}
// 检查权限
boolean granted = hasPermission(authentication, methodInvocationResult);
return new AuthorizationDecision(granted);
}
private boolean hasPermission(Authentication authentication, MethodInvocationResult methodInvocationResult) {
// 获取当前校验方法的返回值
if (methodInvocationResult.getResult() instanceof Result<?> result) {
// 拿到当前返回值中权限内容
List<String> auths = result.getAuths();
// 允许全局访问的 角色或权限
List<String> adminAuthorities = securityConfigProperties.adminAuthorities;
// 判断返回值中返回方法全新啊是否和用户权限匹配
return authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority)
.anyMatch(auth ->
// 允许放行的角色或权限 匹配到的角色或权限
adminAuthorities.contains(auth) || auths.contains(auth)
);
}
// 这里可以设置自己的返回状态
// ======================================
// 默认返回 TRUE 是因为有可能当前方法不需要验证
// 所以才设置默认返回为 TURE
// ======================================
return true;
}
}

View File

@ -1,49 +0,0 @@
package com.auth.module.security.manger;
/**
* 处理方法调用前的授权检查
* check()方法接收的是MethodInvocation对象包含即将执行的方法调用信息
* 用于决定是否允许执行某个方法
* 这是传统的"前置授权"模式
*/
// @Component
// public class PreAuthorizationManager implements AuthorizationManager<MethodInvocation> {
//
// /**
// * 这里两个实现方法按照Security官方要求进行实现
// * <h4>类说明</h4>
// * 下面的实现是对方法执行前进行权限校验的判断
// * <pre>
// * <code>AuthorizationManager &ltMethodInvocation></code>
// * </pre>
// * 下面的这个是对方法执行后对权限的判断
// * <pre>
// * <code>AuthorizationManager &ltMethodInvocationResult></code>
// * </pre>
// *
// * <h4>注意事项</h4>
// * 将上述两个方法按照自定义的方式进行实现后还需要禁用默认的
// * <pre>
// * &#064;Configuration
// * &#064;EnableMethodSecurity(prePostEnabled = false)
// * class MethodSecurityConfig {
// * &#064;Bean
// * &#064;Role(BeanDefinition.ROLE_INFRASTRUCTURE)
// * Advisor preAuthorize(MyAuthorizationManager manager) {
// * return AuthorizationManagerBeforeMethodInterceptor.preAuthorize(manager);
// * }
// *
// * &#064;Bean
// * &#064;Role(BeanDefinition.ROLE_INFRASTRUCTURE)
// * Advisor postAuthorize(MyAuthorizationManager manager) {
// * return AuthorizationManagerAfterMethodInterceptor.postAuthorize(manager);
// * }
// * }
// * </pre>
// */
// @Override
// public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation invocation) {
// return new AuthorizationDecision(true);
// }
//
// }

View File

@ -0,0 +1,106 @@
package com.auth.module.security.manger;// package com.spring.step3.security.manger.demo1;
// import com.auth.module.security.properties.SecurityConfigProperties;
// import lombok.RequiredArgsConstructor;
// import org.aopalliance.intercept.MethodInvocation;
// import org.springframework.core.annotation.AnnotationUtils;
// import org.springframework.security.access.prepost.PreAuthorize;
// import org.springframework.security.authorization.AuthorizationDecision;
// import org.springframework.security.authorization.AuthorizationManager;
// import org.springframework.security.core.Authentication;
// import org.springframework.security.core.GrantedAuthority;
// import org.springframework.stereotype.Component;
//
// import java.util.ArrayList;
// import java.util.List;
// import java.util.function.Supplier;
// import java.util.regex.Matcher;
// import java.util.regex.Pattern;
//
// /**
// * 处理方法调用前的授权检查
// * check()方法接收的是MethodInvocation对象包含即将执行的方法调用信息
// * 用于决定是否允许执行某个方法
// * 这是传统的"前置授权"模式
// */
// @Component
// @RequiredArgsConstructor
// public class PreAuthorizationManagerByCustomer implements AuthorizationManager<MethodInvocation> {
//
// private final SecurityConfigProperties securityConfigProperties;
//
// @Override
// public AuthorizationDecision check(Supplier<Authentication> authenticationSupplier, MethodInvocation methodInvocation) {
// Authentication authentication = authenticationSupplier.get();
//
// // 如果方法有 @PreAuthorize 注解会先到这里
// if (authentication == null || !authentication.isAuthenticated()) {
// return new AuthorizationDecision(false);
// }
//
// // 检查权限
// boolean granted = hasPermission(authentication, methodInvocation);
// return new AuthorizationDecision(granted);
// }
//
// private boolean hasPermission(Authentication authentication, MethodInvocation methodInvocation) {
// PreAuthorize preAuthorize = AnnotationUtils.findAnnotation(methodInvocation.getMethod(), PreAuthorize.class);
// if (preAuthorize == null) {
// return true; // 没有注解默认放行
// }
//
// String expression = preAuthorize.value();
// // 解析表达式中的权限要求
// List<String> requiredAuthorities = extractAuthoritiesFromExpression(expression);
//
// // 获取配置的admin权限
// List<String> adminAuthorities = securityConfigProperties.getAdminAuthorities();
//
// return authentication.getAuthorities().stream()
// .map(GrantedAuthority::getAuthority)
// .anyMatch(auth ->
// adminAuthorities.contains(auth) ||
// requiredAuthorities.contains(auth)
// );
// }
//
// private List<String> extractAuthoritiesFromExpression(String expression) {
// List<String> authorities = new ArrayList<>();
//
// // 处理 hasAuthority('permission') 格式
// Pattern hasAuthorityPattern = Pattern.compile("hasAuthority\\('([^']+)'\\)");
// Matcher hasAuthorityMatcher = hasAuthorityPattern.matcher(expression);
// while (hasAuthorityMatcher.find()) {
// authorities.add(hasAuthorityMatcher.group(1));
// }
//
// // 处理 hasRole('ROLE_XXX') 格式 (Spring Security 会自动添加 ROLE_ 前缀)
// Pattern hasRolePattern = Pattern.compile("hasRole\\('([^']+)'\\)");
// Matcher hasRoleMatcher = hasRolePattern.matcher(expression);
// while (hasRoleMatcher.find()) {
// authorities.add(hasRoleMatcher.group(1));
// }
//
// // 处理 hasAnyAuthority('perm1','perm2') 格式
// Pattern hasAnyAuthorityPattern = Pattern.compile("hasAnyAuthority\\(([^)]+)\\)");
// Matcher hasAnyAuthorityMatcher = hasAnyAuthorityPattern.matcher(expression);
// while (hasAnyAuthorityMatcher.find()) {
// String[] perms = hasAnyAuthorityMatcher.group(1).split(",");
// for (String perm : perms) {
// authorities.add(perm.trim().replaceAll("'", ""));
// }
// }
//
// // 处理 hasAnyRole('role1','role2') 格式
// Pattern hasAnyRolePattern = Pattern.compile("hasAnyRole\\(([^)]+)\\)");
// Matcher hasAnyRoleMatcher = hasAnyRolePattern.matcher(expression);
// while (hasAnyRoleMatcher.find()) {
// String[] roles = hasAnyRoleMatcher.group(1).split(",");
// for (String role : roles) {
// authorities.add(role.trim().replaceAll("'", ""));
// }
// }
//
// return authorities;
// }
// }

View File

@ -0,0 +1,65 @@
package com.auth.module.security.manger;
import com.auth.module.security.config.properties.SecurityConfigProperties;
import lombok.RequiredArgsConstructor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.Expression;
import org.springframework.expression.ParseException;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import java.util.function.Supplier;
@Component
@RequiredArgsConstructor
public class PreAuthorizationManagerByMethod implements AuthorizationManager<MethodInvocation> {
private final SecurityConfigProperties securityConfigProperties;
private final MethodSecurityExpressionHandler expressionHandler;
@Override
public AuthorizationDecision check(Supplier<Authentication> authenticationSupplier, MethodInvocation methodInvocation) {
// 获取方法上的@PreAuthorize注解
PreAuthorize preAuthorize = AnnotationUtils.findAnnotation(methodInvocation.getMethod(), PreAuthorize.class);
if (preAuthorize == null) {
// 没有注解默认放行
return new AuthorizationDecision(true);
}
// 使用Spring的表达式解析器
EvaluationContext ctx = expressionHandler.createEvaluationContext(authenticationSupplier.get(), methodInvocation);
try {
// 解析表达式并获取结果
Expression expression = expressionHandler.getExpressionParser().parseExpression(preAuthorize.value());
boolean granted = Boolean.TRUE.equals(expression.getValue(ctx, Boolean.class));
// 如果表达式不通过检查是否是admin
if (!granted) {
granted = isAdmin(authenticationSupplier.get());
}
return new AuthorizationDecision(granted);
} catch (EvaluationException | ParseException e) {
return new AuthorizationDecision(false);
}
}
private boolean isAdmin(Authentication authentication) {
return securityConfigProperties.getAdminAuthorities().stream()
.anyMatch(auth -> authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.anyMatch(ga -> ga.equals(auth)));
}
}

View File

@ -1 +1,19 @@
如果需要重写验证逻辑(自定义)使用这里面的类,并在配置类`AuthorizationManagerConfiguration`解开注释,
# 自定义判断权限
## 如何开启
在配置文件夹中`config`---`AuthorizationManagerConfiguration`,放开注释的方法即可。
## 前置判断
### PreAuthorizationManagerByCustomer
前置方法有自定义的,通过正则表达式进行匹配这种方式可以实现自定义判断需求,只是实现不够优雅。
### PreAuthorizationManagerByMethod
这种是通过Security自带的方法进行匹配如果当前可以访问所有资源的角色或者权限直接放行。
## 后置判断
根据返回值进行判断的返回值Result中auth进行判断的。

View File

@ -4,4 +4,13 @@ jwtToken:
# 主题
subject: SecurityBunny
# 过期事件 7天
expired: 604800
expired: 604800
# 认证和鉴权配置
security-path:
admin-authorities:
- "ADMIN"
no-auth-paths:
- "/api/public/**"
secured-paths:
- "/api/v1/**"

View File

@ -0,0 +1,78 @@
package com.auth.service.base.controller;
import com.auth.common.model.common.result.PageResult;
import com.auth.common.model.common.result.Result;
import com.auth.common.model.common.result.ResultCodeEnum;
import com.auth.dao.base.entity.base.AuthLogEntity;
import com.auth.model.base.dto.AuthLogDto;
import com.auth.model.base.vo.AuthLogVo;
import com.auth.service.base.service.AuthLogService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* <p>
* 系统授权日志表 前端控制器
* </p>
*
* @author AuthoritySystem
* @since 2025-07-20 12:42:00
*/
@Tag(name = "系统授权日志表", description = "系统授权日志表相关接口")
@RestController
@RequestMapping("/api/v1/base/auth-log")
@RequiredArgsConstructor
public class AuthLogController {
private final AuthLogService authLogService;
@Operation(summary = "分页查询系统授权日志表", description = "分页查询系统授权日志表")
@GetMapping("{page}/{limit}")
public Result<PageResult<AuthLogVo>> getAuthLogPage(
@Parameter(name = "page", description = "当前页", required = true)
@PathVariable("page") Integer page,
@Parameter(name = "limit", description = "每页记录数", required = true)
@PathVariable("limit") Integer limit,
AuthLogDto dto) {
Page<AuthLogEntity> pageParams = new Page<>(page, limit);
PageResult<AuthLogVo> pageResult = authLogService.getAuthLogPage(pageParams, dto);
return Result.success(pageResult);
}
@Operation(summary = "根据id查询系统授权日志表详情", description = "根据id查询系统授权日志表详情")
@GetMapping("{id}")
public Result<AuthLogVo> getAuthLogById(@PathVariable("id") Long id) {
AuthLogVo authLogVo = authLogService.getAuthLogById(id);
return Result.success(authLogVo);
}
@Operation(summary = "添加系统授权日志表", description = "添加系统授权日志表")
@PostMapping()
public Result<String> addAuthLog(@Valid @RequestBody AuthLogDto dto) {
authLogService.addAuthLog(dto);
return Result.success(ResultCodeEnum.ADD_SUCCESS);
}
@Operation(summary = "更新系统授权日志表", description = "更新系统授权日志表")
@PutMapping()
public Result<String> updateAuthLog(@Valid @RequestBody AuthLogDto dto) {
authLogService.updateAuthLog(dto);
return Result.success(ResultCodeEnum.UPDATE_SUCCESS);
}
@Operation(summary = "删除系统授权日志表", description = "删除系统授权日志表")
@DeleteMapping()
public Result<String> deleteAuthLog(@RequestBody List<Long> ids) {
authLogService.deleteAuthLog(ids);
return Result.success(ResultCodeEnum.DELETE_SUCCESS);
}
}

View File

@ -0,0 +1,57 @@
package com.auth.service.base.service;
import com.auth.common.model.common.result.PageResult;
import com.auth.dao.base.entity.base.AuthLogEntity;
import com.auth.model.base.dto.AuthLogDto;
import com.auth.model.base.vo.AuthLogVo;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* <p>
* 系统授权日志表 服务类
* </p>
*
* @author Bunny
* @since 2025-07-19 14:26:58
*/
public interface AuthLogService extends IService<AuthLogEntity> {
/**
* 分页查询系统授权日志表
*
* @return 系统授权日志表分页结果 {@link AuthLogVo}
*/
PageResult<AuthLogVo> getAuthLogPage(Page<AuthLogEntity> pageParams, AuthLogDto dto);
/**
* 根据id查询系统授权日志表详情
*
* @param id 主键
* @return 系统授权日志表详情 AuthLogVo}
*/
AuthLogVo getAuthLogById(Long id);
/**
* 添加系统授权日志表
*
* @param dto {@link AuthLogDto} 添加表单
*/
void addAuthLog(AuthLogDto dto);
/**
* 更新系统授权日志表
*
* @param dto {@link AuthLogDto} 更新表单
*/
void updateAuthLog(AuthLogDto dto);
/**
* 删除|批量删除系统授权日志表类型
*
* @param ids 删除id列表
*/
void deleteAuthLog(List<Long> ids);
}

View File

@ -0,0 +1,99 @@
package com.auth.service.base.service.impl;
import com.auth.common.model.common.result.PageResult;
import com.auth.dao.base.entity.base.AuthLogEntity;
import com.auth.dao.base.mapper.v1.AuthLogMapper;
import com.auth.model.base.dto.AuthLogDto;
import com.auth.model.base.vo.AuthLogVo;
import com.auth.service.base.service.AuthLogService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* <p>
* 系统授权日志表 服务实现类
* </p>
*
* @author Bunny
* @since 2025-07-19 14:26:58
*/
@Service
@Transactional
public class AuthLogServiceImpl extends ServiceImpl<AuthLogMapper, AuthLogEntity> implements AuthLogService {
/**
* 系统授权日志表 服务实现类
*
* @param pageParams 系统授权日志表分页查询page对象
* @param dto 系统授权日志表分页查询对象
* @return 查询分页系统授权日志表返回对象
*/
@Override
public PageResult<AuthLogVo> getAuthLogPage(Page<AuthLogEntity> pageParams, AuthLogDto dto) {
IPage<AuthLogVo> page = baseMapper.selectListByPage(pageParams, dto);
return PageResult.<AuthLogVo>builder()
.list(page.getRecords())
.pageNo(page.getCurrent())
.pageSize(page.getSize())
.total(page.getTotal())
.build();
}
/**
* 根据id查询系统授权日志表详情
*
* @param id 主键
* @return 系统授权日志表详情 AuthLogVo}
*/
public AuthLogVo getAuthLogById(Long id) {
AuthLogEntity authLogEntity = getById(id);
AuthLogVo authLogVo = new AuthLogVo();
BeanUtils.copyProperties(authLogEntity, authLogVo);
return authLogVo;
}
/**
* 添加系统授权日志表
*
* @param dto 系统授权日志表添加
*/
@Override
public void addAuthLog(AuthLogDto dto) {
AuthLogEntity authLog = new AuthLogEntity();
BeanUtils.copyProperties(dto, authLog);
save(authLog);
}
/**
* 更新系统授权日志表
*
* @param dto 系统授权日志表更新
*/
@Override
public void updateAuthLog(AuthLogDto dto) {
AuthLogEntity authLog = new AuthLogEntity();
BeanUtils.copyProperties(dto, authLog);
updateById(authLog);
}
/**
* 删除|批量删除系统授权日志表
*
* @param ids 删除id列表
*/
@Override
public void deleteAuthLog(List<Long> ids) {
removeByIds(ids);
}
}

View File

@ -5,9 +5,3 @@ bunny:
database: test_auth
username: bunny_test
password: "Test1234"
testJwt:
host: rm-bp12z6hlv46vi6g8mro.mysql.rds.aliyuncs.com
port: 3306
database: test_jwt
username: bunny_test
password: "Test1234"