paramMap = ServletUtil.getParamMap(request);
+ authRequest = BeanUtil.toBean(paramMap, SpaceUserAuthContext.class);
+ }
+ // 根据请求路径区分 id 字段的含义
+ Long id = authRequest.getId();
+ if (ObjUtil.isNotNull(id)) {
+ // 获取到请求路径的业务前缀,/api/picture/aaa?a=1
+ String requestURI = request.getRequestURI();
+ // 先替换掉上下文,剩下的就是前缀
+ String partURI = requestURI.replace(contextPath + "/", "");
+ // 获取前缀的第一个斜杠前的字符串
+ String moduleName = StrUtil.subBefore(partURI, "/", false);
+ switch (moduleName) {
+ case "picture":
+ authRequest.setPictureId(id);
+ break;
+ case "spaceUser":
+ authRequest.setSpaceUserId(id);
+ break;
+ case "space":
+ authRequest.setSpaceId(id);
+ break;
+ default:
+ }
+ }
+ return authRequest;
+ }
+
+ /**
+ * 判断对象的所有字段是否为空
+ *
+ * @param object
+ * @return
+ */
+ private boolean isAllFieldsNull(Object object) {
+ if (object == null) {
+ return true; // 对象本身为空
+ }
+ // 获取所有字段并判断是否所有字段都为空
+ return Arrays.stream(ReflectUtil.getFields(object.getClass()))
+ // 获取字段值
+ .map(field -> ReflectUtil.getFieldValue(object, field))
+ // 检查是否所有字段都为空
+ .allMatch(ObjectUtil::isEmpty);
+ }
+}
diff --git a/src/main/java/edu/whut/smilepicturebackend/manager/auth/StpKit.java b/src/main/java/edu/whut/smilepicturebackend/manager/auth/StpKit.java
new file mode 100644
index 0000000..1eebd3b
--- /dev/null
+++ b/src/main/java/edu/whut/smilepicturebackend/manager/auth/StpKit.java
@@ -0,0 +1,25 @@
+package edu.whut.smilepicturebackend.manager.auth;
+
+import cn.dev33.satoken.stp.StpLogic;
+import cn.dev33.satoken.stp.StpUtil;
+import org.springframework.stereotype.Component;
+
+/**
+ * StpLogic 门面类,管理项目中所有的 StpLogic 账号体系
+ * 添加 @Component 注解的目的是确保静态属性 DEFAULT 和 SPACE 被初始化
+ */
+@Component
+public class StpKit {
+
+ public static final String SPACE_TYPE = "space";
+
+ /**
+ * 默认原生会话对象,项目中目前没使用到
+ */
+ public static final StpLogic DEFAULT = StpUtil.stpLogic;
+
+ /**
+ * Space 会话对象,管理 Space 表所有账号的登录、权限认证
+ */
+ public static final StpLogic SPACE = new StpLogic(SPACE_TYPE);
+}
\ No newline at end of file
diff --git a/src/main/java/edu/whut/smilepicturebackend/manager/auth/annotation/SaSpaceCheckPermission.java b/src/main/java/edu/whut/smilepicturebackend/manager/auth/annotation/SaSpaceCheckPermission.java
new file mode 100644
index 0000000..164555c
--- /dev/null
+++ b/src/main/java/edu/whut/smilepicturebackend/manager/auth/annotation/SaSpaceCheckPermission.java
@@ -0,0 +1,57 @@
+package edu.whut.smilepicturebackend.manager.auth.annotation;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.annotation.SaMode;
+
+import edu.whut.smilepicturebackend.manager.auth.StpKit;
+import org.springframework.core.annotation.AliasFor;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 空间权限认证:必须具有指定权限才能进入该方法
+ * 可标注在函数、类上(效果等同于标注在此类的所有方法上)
+ */
+@SaCheckPermission(type = StpKit.SPACE_TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface SaSpaceCheckPermission {
+
+ /**
+ * 需要校验的权限码
+ *
+ * @return 需要校验的权限码
+ */
+ @AliasFor(annotation = SaCheckPermission.class)
+ String[] value() default {};
+
+ /**
+ * 验证模式:AND | OR,默认AND
+ *
+ * @return 验证模式
+ */
+ @AliasFor(annotation = SaCheckPermission.class)
+ SaMode mode() default SaMode.AND;
+
+ /**
+ * 在权限校验不通过时的次要选择,两者只要其一校验成功即可通过校验
+ *
+ *
+ * 例1:@SaCheckPermission(value="user-add", orRole="admin"),
+ * 代表本次请求只要具有 user-add权限 或 admin角色 其一即可通过校验。
+ *
+ *
+ *
+ * 例2: orRole = {"admin", "manager", "staff"},具有三个角色其一即可。
+ * 例3: orRole = {"admin, manager, staff"},必须三个角色同时具备。
+ *
+ *
+ * @return /
+ */
+ @AliasFor(annotation = SaCheckPermission.class)
+ String[] orRole() default {};
+
+}
diff --git a/src/main/java/edu/whut/smilepicturebackend/manager/auth/annotation/SaTokenConfigure.java b/src/main/java/edu/whut/smilepicturebackend/manager/auth/annotation/SaTokenConfigure.java
new file mode 100644
index 0000000..af36409
--- /dev/null
+++ b/src/main/java/edu/whut/smilepicturebackend/manager/auth/annotation/SaTokenConfigure.java
@@ -0,0 +1,32 @@
+package edu.whut.smilepicturebackend.manager.auth.annotation;
+
+import cn.dev33.satoken.interceptor.SaInterceptor;
+import cn.dev33.satoken.strategy.SaAnnotationStrategy;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.AnnotatedElementUtils;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * Sa-Token 开启注解和配置
+ */
+@Configuration
+public class SaTokenConfigure implements WebMvcConfigurer {
+
+ // 注册 Sa-Token 拦截器,打开注解式鉴权功能
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ // 注册 Sa-Token 拦截器,打开注解式鉴权功能
+ registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");
+ }
+
+ @PostConstruct
+ public void rewriteSaStrategy() {
+ // 重写Sa-Token的注解处理器,增加注解合并功能
+ SaAnnotationStrategy.instance.getAnnotation = (element, annotationClass) -> {
+ return AnnotatedElementUtils.getMergedAnnotation(element, annotationClass);
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/edu/whut/smilepicturebackend/manager/auth/model/SpaceUserAuthConfig.java b/src/main/java/edu/whut/smilepicturebackend/manager/auth/model/SpaceUserAuthConfig.java
new file mode 100644
index 0000000..4341a03
--- /dev/null
+++ b/src/main/java/edu/whut/smilepicturebackend/manager/auth/model/SpaceUserAuthConfig.java
@@ -0,0 +1,25 @@
+package edu.whut.smilepicturebackend.manager.auth.model;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 空间成员权限配置
+ */
+@Data
+public class SpaceUserAuthConfig implements Serializable {
+
+ /**
+ * 权限列表
+ */
+ private List permissions;
+
+ /**
+ * 角色列表
+ */
+ private List roles;
+
+ private static final long serialVersionUID = 1L;
+}
\ No newline at end of file
diff --git a/src/main/java/edu/whut/smilepicturebackend/manager/auth/model/SpaceUserPermission.java b/src/main/java/edu/whut/smilepicturebackend/manager/auth/model/SpaceUserPermission.java
new file mode 100644
index 0000000..458b653
--- /dev/null
+++ b/src/main/java/edu/whut/smilepicturebackend/manager/auth/model/SpaceUserPermission.java
@@ -0,0 +1,30 @@
+package edu.whut.smilepicturebackend.manager.auth.model;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 空间成员权限
+ */
+@Data
+public class SpaceUserPermission implements Serializable {
+
+ /**
+ * 权限键
+ */
+ private String key;
+
+ /**
+ * 权限名称
+ */
+ private String name;
+
+ /**
+ * 权限描述
+ */
+ private String description;
+
+ private static final long serialVersionUID = 1L;
+
+}
\ No newline at end of file
diff --git a/src/main/java/edu/whut/smilepicturebackend/manager/auth/model/SpaceUserPermissionConstant.java b/src/main/java/edu/whut/smilepicturebackend/manager/auth/model/SpaceUserPermissionConstant.java
new file mode 100644
index 0000000..b6d13d9
--- /dev/null
+++ b/src/main/java/edu/whut/smilepicturebackend/manager/auth/model/SpaceUserPermissionConstant.java
@@ -0,0 +1,32 @@
+package edu.whut.smilepicturebackend.manager.auth.model;
+
+/**
+ * 空间成员权限常量
+ */
+public interface SpaceUserPermissionConstant {
+
+ /**
+ * 空间用户管理权限
+ */
+ String SPACE_USER_MANAGE = "spaceUser:manage";
+
+ /**
+ * 图片查看权限
+ */
+ String PICTURE_VIEW = "picture:view";
+
+ /**
+ * 图片上传权限
+ */
+ String PICTURE_UPLOAD = "picture:upload";
+
+ /**
+ * 图片编辑权限
+ */
+ String PICTURE_EDIT = "picture:edit";
+
+ /**
+ * 图片删除权限
+ */
+ String PICTURE_DELETE = "picture:delete";
+}
\ No newline at end of file
diff --git a/src/main/java/edu/whut/smilepicturebackend/manager/auth/model/SpaceUserRole.java b/src/main/java/edu/whut/smilepicturebackend/manager/auth/model/SpaceUserRole.java
new file mode 100644
index 0000000..dd0e641
--- /dev/null
+++ b/src/main/java/edu/whut/smilepicturebackend/manager/auth/model/SpaceUserRole.java
@@ -0,0 +1,35 @@
+package edu.whut.smilepicturebackend.manager.auth.model;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 空间成员角色
+ */
+@Data
+public class SpaceUserRole implements Serializable {
+
+ /**
+ * 角色键
+ */
+ private String key;
+
+ /**
+ * 角色名称
+ */
+ private String name;
+
+ /**
+ * 权限键列表
+ */
+ private List permissions;
+
+ /**
+ * 角色描述
+ */
+ private String description;
+
+ private static final long serialVersionUID = 1L;
+}
\ No newline at end of file
diff --git a/src/main/java/edu/whut/smilepicturebackend/service/impl/PictureServiceImpl.java b/src/main/java/edu/whut/smilepicturebackend/service/impl/PictureServiceImpl.java
index 8ab359d..f965b54 100644
--- a/src/main/java/edu/whut/smilepicturebackend/service/impl/PictureServiceImpl.java
+++ b/src/main/java/edu/whut/smilepicturebackend/service/impl/PictureServiceImpl.java
@@ -282,8 +282,8 @@ public class PictureServiceImpl extends ServiceImpl
&& !userService.isAdmin(loginUser)) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
}
- // 校验权限
- checkPictureAuth(loginUser, oldPicture);
+ // 校验权限,已改为注解鉴权
+// checkPictureAuth(loginUser, oldPicture);
// 开启事务
transactionTemplate.execute(status -> {
// 操作数据库
@@ -317,8 +317,8 @@ public class PictureServiceImpl extends ServiceImpl
long id = pictureEditRequest.getId();
Picture oldPicture = this.getById(id);
ThrowUtils.throwIf(oldPicture == null, ErrorCode.NOT_FOUND_ERROR);
- // 校验权限
- checkPictureAuth(loginUser, oldPicture);
+ // 校验权限,已改为注解鉴权
+// checkPictureAuth(loginUser, oldPicture);
// 补充审核 参数,每次编辑图片都要重新过审
this.fillReviewParams(picture, loginUser);
// 操作数据库
diff --git a/src/main/java/edu/whut/smilepicturebackend/service/impl/UserServiceImpl.java b/src/main/java/edu/whut/smilepicturebackend/service/impl/UserServiceImpl.java
index ccfec7c..3b6edf9 100644
--- a/src/main/java/edu/whut/smilepicturebackend/service/impl/UserServiceImpl.java
+++ b/src/main/java/edu/whut/smilepicturebackend/service/impl/UserServiceImpl.java
@@ -14,6 +14,7 @@ import edu.whut.smilepicturebackend.constant.UserConstant;
import edu.whut.smilepicturebackend.exception.BusinessException;
import edu.whut.smilepicturebackend.exception.ErrorCode;
import edu.whut.smilepicturebackend.exception.ThrowUtils;
+import edu.whut.smilepicturebackend.manager.auth.StpKit;
import edu.whut.smilepicturebackend.model.dto.user.UserAddRequest;
import edu.whut.smilepicturebackend.model.dto.user.UserQueryRequest;
import edu.whut.smilepicturebackend.model.entity.User;
@@ -127,6 +128,10 @@ public class UserServiceImpl extends ServiceImpl
}
// 4. 保存用户的登录态
request.getSession().setAttribute(UserConstant.USER_LOGIN_STATE, user);
+ // 记录用户登录态到 Sa-token,便于空间鉴权时使用,注意保证该用户信息与 SpringSession 中的信息过期时间一致
+
+ StpKit.SPACE.login(user.getId());
+ StpKit.SPACE.getSession().set(UserConstant.USER_LOGIN_STATE, user);
return this.getLoginUserVO(user);
}
diff --git a/src/main/resources/biz/spaceUserAuthConfig.json b/src/main/resources/biz/spaceUserAuthConfig.json
new file mode 100644
index 0000000..0b49c6f
--- /dev/null
+++ b/src/main/resources/biz/spaceUserAuthConfig.json
@@ -0,0 +1,62 @@
+{
+ "permissions": [
+ {
+ "key": "spaceUser:manage",
+ "name": "成员管理",
+ "description": "管理空间成员,添加或移除成员"
+ },
+ {
+ "key": "picture:view",
+ "name": "查看图片",
+ "description": "查看空间中的图片内容"
+ },
+ {
+ "key": "picture:upload",
+ "name": "上传图片",
+ "description": "上传图片到空间中"
+ },
+ {
+ "key": "picture:edit",
+ "name": "修改图片",
+ "description": "编辑已上传的图片信息"
+ },
+ {
+ "key": "picture:delete",
+ "name": "删除图片",
+ "description": "删除空间中的图片"
+ }
+ ],
+ "roles": [
+ {
+ "key": "viewer",
+ "name": "浏览者",
+ "permissions": [
+ "picture:view"
+ ],
+ "description": "查看图片"
+ },
+ {
+ "key": "editor",
+ "name": "编辑者",
+ "permissions": [
+ "picture:view",
+ "picture:upload",
+ "picture:edit",
+ "picture:delete"
+ ],
+ "description": "查看图片、上传图片、修改图片、删除图片"
+ },
+ {
+ "key": "admin",
+ "name": "管理员",
+ "permissions": [
+ "spaceUser:manage",
+ "picture:view",
+ "picture:upload",
+ "picture:edit",
+ "picture:delete"
+ ],
+ "description": "成员管理、查看图片、上传图片、修改图片、删除图片"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html
new file mode 100644
index 0000000..89bb8ba
--- /dev/null
+++ b/src/main/resources/static/index.html
@@ -0,0 +1,6 @@
+
+
+hello word!!!
+this is a html page
+
+
\ No newline at end of file