当前位置: 首页 > news >正文

让我们从hello world开始-认证实现

各位朋友好,又见面了,我们来简单回顾一下上次做了什么,我们基本实现了一个简单的认证功能包括,前台的登入页面,前后的相互交互 ,并完成了后端的认证,我相信大多数有经验的小伙伴一定知道后面我会去实现权限控制的功能,其实我原本可以直接在认证开始就带着权限功能一起实现,如果你知道在认证开始就要想着如何设计权限认证功能,那么是你的经验和财富。但是我相信看到这篇文章的人并不全部都是经验丰富的开发者,所以我选择实现一个并不完整功能,然后在一点点完善。这也是我想和很多没有那么资深的开发者表达的,当你面对一个全新位置的功能,一开始就去实现一个完善的功能是不现实的,去过多的思考功能的完善程度只能阻碍你去放手去做的信息,所有的工程化的方法思路都是一开始想要去完成一个目标,并将分为各个不同的小目标,在完成一个不同小目标的过程中不断去修正你的方法和思路,去跨过一个又一个阶段,最终达成一个结果。当然这个结果可能和你一开始的目标并不相同,可能更好也可能更坏。但是这个过程中的经验和教训才是你的财富。这个工程的话思想,使用于所有长期去做的事情,无论是工作,学习,亦或者健身运动,甚至是人生。

好了私货夹带的有点对了,那么我们赶紧开始我们的下一步工作,如果你并没有思路和头绪,不妨在借助ai,以下是我的关键词

当我已经有基于jwt的认证功能,我想在加入权限控制功能如何加入 给我个解决方案即可。

相信如果你非常了解关键词,你可能会认为我的关键词非常的业余,既没有角色的定义,也没有具体的规则,但是我在这里会继续提起我在上篇文章结尾,说到的提示语范式,相信模型的智能,多做引导而非指定规则。

基于您已有的JWT认证功能,要加入权限控制功能,需要构建一个完整的基于角色的访问控制(RBAC)系统。以下是结合多个最佳实践的综合解决方案:

一、后端权限控制架构设计

1. 定义细粒度权限模型

首先需要建立清晰的权限模型,这是权限控制的基础。创建权限枚举和角色枚举类,实现权限的细粒度控制

。权限枚举定义具体的操作权限(如user:readuser:write),角色枚举则组合这些权限,并为每个角色生成对应的权限集合。这种设计支持方法级的权限控制,比简单的角色控制更加灵活和安全。

2. 增强用户实体与JWT令牌

修改现有的用户实体类,使其实现Spring Security的UserDetails接口,并包含角色信息

。在生成JWT令牌时,需要包含用户的角色和权限信息,这样在后续的请求中可以直接从令牌中解析出用户的权限,无需频繁查询数据库。同时,在UserDetailsService的实现中,需要正确加载用户的权限集合,确保Spring Security能够识别用户的权限。

3. 配置Spring Security权限规则

在安全配置中定义细粒度的权限控制规则。Spring Security 6.0采用了新的配置范式,摒弃了WebSecurityConfigurerAdapter,转而使用Lambda DSL与组件化配置模式

。通过SecurityFilterChainBean的定义,可以实现更清晰的配置分离。配置应包括:
  • 公开接口的访问权限
  • 基于HTTP方法和权限的细粒度控制
  • 基于角色的访问控制
  • 启用方法级权限控制注解支持

4. 实现方法级权限控制

使用@PreAuthorize注解在控制器方法上实现更细粒度的权限控制

。这种方法允许在方法级别定义访问规则,如@PreAuthorize("hasAuthority('user:read') or hasAuthority('admin:read')")。确保在SecurityConfig中启用@EnableMethodSecurity注解,以支持方法级的安全控制。

二、前端权限控制实现

1. 存储用户权限信息

登录成功后,前端需要保存用户的角色和权限信息到本地存储(如localStorage或sessionStorage)。这些信息包括用户ID、用户名、角色和权限列表,用于后续的权限验证和界面控制。

2. 实现路由守卫

在前端路由中实现基于权限的路由守卫,控制用户能否访问某个页面

。路由守卫应检查:
  • 用户是否已登录(检查token是否存在)
  • 用户是否有访问该路由所需的权限
  • 用户是否有访问该路由所需的角色
    对于无权限的访问,应重定向到403页面或登录页面。

3. 实现按钮级权限控制

在前端组件中实现按钮级别的权限控制,根据用户的权限动态显示或隐藏功能按钮。这可以通过自定义指令或组件封装实现,确保用户只能看到和操作自己有权限的功能。

三、权限控制层级体系

完整的权限控制应包含四个层级:

1. 路由权限控制

控制用户能否访问某个页面,通过前端路由守卫实现。

2. 菜单权限控制

根据用户角色和权限动态生成可访问的菜单项,确保用户只能看到自己有权限访问的菜单。

3. 按钮权限控制

控制页面内具体功能按钮的显示与隐藏,实现界面级的权限控制。

4. 接口权限控制

后端API接口的权限验证,确保即使前端绕过检查,后端也会拒绝未授权的请求

。这是最后一道防线,也是最重要的安全保证。

四、高级功能增强

1. Token自动续期机制

每次成功访问受保护接口时,过滤器判断Token剩余时间是否低于阈值(如10分钟),如果是则自动签发新Token并通过响应头返回

。前端监听该响应头并自动更新本地Token,实现无感知的Token续期。

2. Token黑名单机制

用户退出登录时,将当前Token加入黑名单(可用Redis设置自动过期)

。在过滤器中拒绝黑名单内的Token,确保退出登录后Token立即失效。黑名单使用Redis TTL自动过期,无需手动清理。

3. 动态权限决策

自定义AccessDecisionManager,集成业务规则引擎,实现基于时间、IP等维度的动态授权

。例如,可以限制某些敏感操作只能在特定时间段或特定IP地址下执行。

4. 权限数据动态管理

考虑将角色和权限信息存储在数据库中,实现动态配置。这样可以在不重启应用的情况下修改权限分配,支持更灵活的业务需求。

五、安全优化与性能考虑

1. 签名算法选择

根据部署架构选择合适的签名算法:HMAC算法适用于单节点部署,签名速度快但密钥分发复杂;RSA算法通过公私钥对实现令牌签发与验证,适合微服务架构下的分布式验证

2. 高并发场景优化

在高并发场景下,可以采用以下策略优化性能:

  • 令牌解析缓存:对频繁访问的JWT载荷进行本地缓存,减少重复解析开销
  • 异步非阻塞验证:结合WebFlux,通过ServerHttpSecurity实现非阻塞式令牌验证

3. 统一异常处理

自定义异常处理器,统一处理认证和授权异常,返回规范的JSON格式错误信息

。包括:
  • 未登录或无效Token(401)
  • 权限不足(403)
  • 登录失败(401)

六、实施步骤建议

  1. 评估现有系统:分析现有的JWT认证实现,确定需要修改的部分
  2. 设计权限模型:根据业务需求设计角色和权限体系
  3. 后端改造:依次实现权限模型、增强用户实体、配置Security、实现方法级控制
  4. 前端改造:实现路由守卫、菜单控制、按钮控制
  5. 高级功能集成:根据需要添加Token续期、黑名单等高级功能
  6. 测试验证:编写全面的测试用例,验证权限控制的正确性
  7. 监控审计:添加权限相关的日志记录,便于审计和问题排查

通过以上方案,您可以在现有的JWT认证基础上,构建一个完整、安全、可扩展的权限控制系统。这个系统不仅能够满足基本的权限控制需求,还支持高级功能如动态权限管理、令牌刷新和黑名单机制,为企业级应用提供了坚实的安全基础

那么我们看,我们的ai给了我们一个什么样的回复,基于上面的内容我给大家分析下我的提示词生成逻辑。

首先看后端

1. 定义细粒度权限模型

首先需要建立清晰的权限模型,这是权限控制的基础。创建权限枚举和角色枚举类,实现权限的细粒度控制

。权限枚举定义具体的操作权限(如user:readuser:write),角色枚举则组合这些权限,并为每个角色生成对应的权限集合。这种设计支持方法级的权限控制,比简单的角色控制更加灵活和安全。

1.生成用户角色权限的关系表和对应关系,其中用户可以有多个角色,一个角色可以有多个权限。

2. 增强用户实体与JWT令牌

修改现有的用户实体类,使其实现Spring Security的UserDetails接口,并包含角色信息

。在生成JWT令牌时,需要包含用户的角色和权限信息,这样在后续的请求中可以直接从令牌中解析出用户的权限,无需频繁查询数据库。同时,在UserDetailsService的实现中,需要正确加载用户的权限集合,确保Spring Security能够识别用户的权限。

3. 配置Spring Security权限规则

在安全配置中定义细粒度的权限控制规则。Spring Security 6.0采用了新的配置范式,摒弃了WebSecurityConfigurerAdapter,转而使用Lambda DSL与组件化配置模式

。通过SecurityFilterChainBean的定义,可以实现更清晰的配置分离。配置应包括:

  • 公开接口的访问权限
  • 基于HTTP方法和权限的细粒度控制
  • 基于角色的访问控制
  • 启用方法级权限控制注解支持

4. 实现方法级权限控制

使用@PreAuthorize注解在控制器方法上实现更细粒度的权限控制

。这种方法允许在方法级别定义访问规则,如@PreAuthorize("hasAuthority('user:read') or hasAuthority('admin:read')")。确保在SecurityConfig中启用@EnableMethodSecurity注解,以支持方法级的安全控制。

2.引入Spring Security在生成JWT令牌时,需要包含用户的角色和权限信息,这样在后续的请求中可以直接从令牌中解析出用户的权限,无需频繁查询数据库。同时,在UserDetailsService的实现中,需要正确加载用户的权限集合,确保Spring Security能够识别用户的权限。

我们使用ai帮我生成了代码,同时ai还贴心的给我们生成了一个说明,真是我的好牛马

# 用户角色权限系统实现说明 ## 概述 本系统实现了基于 Spring Security 的用户角色权限(RBAC)管理系统,支持: - 用户-角色-权限的多对多关系 - JWT 令牌中包含用户角色和权限信息 - 从 JWT 令牌中解析权限,无需频繁查询数据库 - Spring Security 方法级权限控制 ## 数据库表结构 ### 主要表 1. **sys_user** - 用户表(已存在) 2. **sys_role** - 角色表 3. **sys_permission** - 权限表 4. **sys_user_role** - 用户角色关联表 5. **sys_role_permission** - 角色权限关联表 ### 表关系 - 一个用户可以有多个角色(sys_user_role) - 一个角色可以有多个权限(sys_role_permission) - 通过角色间接实现用户和权限的多对多关系 ## 实体类 ### 新增实体 - `Role.java` - 角色实体 - `Permission.java` - 权限实体 - `UserRole.java` - 用户角色关联实体 - `RolePermission.java` - 角色权限关联实体 ### 修改实体 - `User.java` - 添加了 `roles` 属性 ## 核心组件 ### 1. CustomUserDetails `com.documentagent.gateway.domain.user.security.CustomUserDetails` - 实现 Spring Security 的 `UserDetails` 接口 - 包含用户、角色、权限信息 - 提供权限集合供 Spring Security 使用 ### 2. CustomUserDetailsService `com.documentagent.gateway.application.service.CustomUserDetailsService` - 实现 Spring Security 的 `UserDetailsService` 接口 - 加载用户的角色和权限信息 - 提供基于用户名和用户ID的加载方法 ### 3. JwtUtil `com.documentagent.gateway.common.util.JwtUtil` **修改内容**: - `generateToken()` 方法现在支持角色和权限参数 - 新增 `getRolesFromToken()` 方法 - 新增 `getPermissionsFromToken()` 方法 **使用示例**: ```java String token = jwtUtil.generateToken(userId, username, roles, permissions); List<String> roles = jwtUtil.getRolesFromToken(token); List<String> permissions = jwtUtil.getPermissionsFromToken(token); ``` ### 4. JwtAuthenticationFilter `com.documentagent.gateway.common.filter.JwtAuthenticationFilter` **功能**: - 从请求中提取 JWT 令牌 - 验证令牌有效性 - 从令牌中解析角色和权限信息 - 设置 Spring Security 上下文 ### 5. SecurityConfig `com.documentagent.gateway.infrastructure.config.SecurityConfig` **配置内容**: - 启用 Web 安全 - 启用方法级安全(`@PreAuthorize` 等注解) - 配置 JWT 认证过滤器 - 配置密码编码器(BCrypt) - 配置无需认证的路径 ## JWT 令牌结构 ```json { "userId": 1, "username": "admin", "roles": ["ROLE_ADMIN", "ROLE_USER"], "permissions": ["document:read", "document:write"], "iat": 1234567890, "exp": 1234654290 } ``` ## 工具类 ### SecurityUtils `com.documentagent.gateway.common.util.SecurityUtils` 提供静态方法获取当前用户信息: ```java CustomUserDetails user = SecurityUtils.getCurrentUser(); Long userId = SecurityUtils.getCurrentUserId(); String username = SecurityUtils.getCurrentUsername(); boolean isAuth = SecurityUtils.isAuthenticated(); ``` ### RequestUtils `com.documentagent.gateway.common.util.RequestUtils` 从 HttpServletRequest 中获取用户信息: ```java Long userId = RequestUtils.getUserIdFromRequest(request); List<String> roles = RequestUtils.getRolesFromRequest(request); List<String> permissions = RequestUtils.getPermissionsFromRequest(request); ``` ## 注解 ### @RequiresPermission `com.documentagent.gateway.common.annotation.RequiresPermission` 方法级权限检查: ```java @RequiresPermission("document:write") public void createDocument(Document document) { // 只有拥有 document:write 权限的用户才能执行 } ``` ### @RequiresRole `com.documentagent.gateway.common.annotation.RequiresRole` 方法级角色检查: ```java @RequiresRole("ROLE_ADMIN") public void deleteUser(Long userId) { // 只有管理员才能执行 } ``` ## 使用示例 ### 登录时生成包含权限的令牌 ```java @Autowired private CustomUserDetailsService userDetailsService; public LoginResponse login(LoginRequest request) { User user = userMapper.selectOne(...); CustomUserDetails userDetails = userDetailsService.loadUserById(user.getId()); List<String> roles = userDetails.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .filter(auth -> auth.startsWith("ROLE_")) .collect(Collectors.toList()); List<String> permissions = userDetails.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .filter(auth -> !auth.startsWith("ROLE_")) .collect(Collectors.toList()); String token = jwtUtil.generateToken(user.getId(), user.getUsername(), roles, permissions); return new LoginResponse(token, user.getId(), user.getUsername(), user.getEmail(), roles, permissions); } ``` ### 方法级权限控制 ```java @RestController @RequestMapping("/documents") public class DocumentController { @GetMapping("/{id}") @PreAuthorize("hasAuthority('document:read')") public Document getDocument(@PathVariable Long id) { // 只有拥有 document:read 权限的用户才能访问 } @PostMapping @PreAuthorize("hasAnyRole('ADMIN', 'DOC_ADMIN')") public Document createDocument(@RequestBody DocumentCreateCommand command) { // 只有 ADMIN 或 DOC_ADMIN 角色的用户才能访问 } @DeleteMapping("/{id}") @PreAuthorize("hasRole('ADMIN')") public void deleteDocument(@PathVariable Long id) { // 只有 ADMIN 角色的用户才能访问 } } ``` ## 数据库初始化 执行 `resources/db/schema_rbac.sql` 脚本创建表结构和初始化数据。 ### 默认角色 1. **ROLE_ADMIN** - 超级管理员(拥有所有权限) 2. **ROLE_USER** - 普通用户(部分文档权限) 3. **ROLE_DOC_ADMIN** - 文档管理员(文档管理所有权限) ### 默认权限 - **系统管理**:用户管理、角色管理、权限管理 - **文档管理**:查看、创建、编辑、删除 - **API权限**:文档API、版本API、用户API ## 注意事项 1. **密码迁移**:原有系统使用 MD5 加密,新系统使用 BCrypt。需要为现有用户更新密码。 2. **令牌刷新**:用户权限变更后,需要重新登录或刷新令牌。 3. **性能优化**:JWT 令牌中包含权限信息,减少了数据库查询,但需要注意令牌大小。 4. **安全建议**: - 生产环境应使用更长的 JWT 密钥 - 敏感操作建议结合数据库权限验证 - 定期更换 JWT 密钥 ## 下一步 1. 创建角色管理 API 2. 创建权限管理 API 3. 创建用户角色分配 API 4. 添加权限变更通知机制 5. 实现细粒度的数据权限控制

ok,我们完成了权限的功能,回顾这个一切来的简直困难(笑),但是一起都是值得的,但是这依旧存在这个问题,存在什么问题呢,我相信聪明的你已经看出了,没错使用方式,在我们的这套解决方案上如何去做权限的变化呢?不好意思只能进行编码的修改,这可不行,总不能给用户设置个权限就修改一次代码吧,这不是玩傻子吗,我们需要能动态修改权限的功能,但是有点困难呢,别担心我们有最好的伙伴。

@PostMapping @PreAuthorize("hasAnyRole('ADMIN', 'DOC_ADMIN')") public Document createDocument(@RequestBody DocumentCreateCommand command) { // 只有 ADMIN 或 DOC_ADMIN 角色的用户才能访问 } 如果我的角色变成可配置如何去做

这是我们的提示语,甚至这都不算提示语只是一个简单的问题,其实现阶段我们并不需要负责的提示语来帮助我们引导ai做东西,因为我们写的还是java工程,如果换到ai应用的部分我们可能就需要好好琢磨我们的提示语了,当时这些事我们后续再谈。

基于您的代码片段和问题,要实现角色的动态可配置化,核心思路是将硬编码在注解中的角色信息(如'ADMIN', 'DOC_ADMIN')转移到外部数据源(如数据库),并在运行时根据这些配置进行权限决策。以下是实现此目标的几种主要方案,结合了搜索结果中的最佳实践

方案一:基于数据库的动态URL权限规则(推荐用于接口级控制)

此方案的核心是自定义FilterInvocationSecurityMetadataSource,它允许您根据数据库中的配置,动态决定每个URL(如您的@PostMapping端点)需要哪些角色才能访问

  1. 数据库设计
    您需要在现有用户、角色表的基础上,增加资源表资源-角色关联表

    • 资源表:存储系统中的受保护资源,通常包括资源ID、URL模式(如/api/documents)、资源名称等字段。
    • 资源-角色关联表:建立资源与角色之间的多对多关系,定义访问某个URL模式需要具备哪些角色。
  2. 自定义安全元数据源
    实现FilterInvocationSecurityMetadataSource接口,重写其getAttributes方法。此方法会在每次请求时被调用,用于根据当前请求的URL,从数据库中查询出访问该URL所需的所有角色

    java

    @Component public class DynamicSecurityMetadataSource implements FilterInvocationSecurityMetadataSource { @Autowired private ResourceService resourceService; // 您的服务,用于查询数据库 private AntPathMatcher antPathMatcher = new AntPathMatcher(); @Override public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { String requestUrl = ((FilterInvocation) object).getRequestUrl(); // 1. 从数据库或缓存中,查询所有“URL模式-所需角色”的配置 List<Resource> allResources = resourceService.getAllResourcesWithRoles(); // 2. 匹配当前请求的URL for (Resource resource : allResources) { if (antPathMatcher.match(resource.getUrlPattern(), requestUrl)) { // 3. 返回该URL所需角色的集合 List<String> roleNames = resource.getRequiredRoles().stream() .map(Role::getName) .collect(Collectors.toList()); return SecurityConfig.createList(roleNames.toArray(new String); } } // 4. 如果没有匹配到规则,可以返回一个默认角色(如要求登录)或抛出异常 return SecurityConfig.createList("ROLE_LOGIN"); } // ... 其他必须实现的方法 }
  3. 集成到Spring Security配置
    在您的安全配置类(如WebSecurityConfig)中,通过withObjectPostProcessor方法,将自定义的DynamicSecurityMetadataSource和对应的AccessDecisionManager注入到安全过滤器链中

    java

    @Configuration @EnableWebSecurity public class SecurityConfig { @Autowired private DynamicSecurityMetadataSource dynamicSecurityMetadataSource; @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authorize -> authorize .anyRequest().authenticated() .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() { @Override public <O extends FilterSecurityInterceptor> O postProcess(O interceptor) { interceptor.setSecurityMetadataSource(dynamicSecurityMetadataSource); // 可以同时设置自定义的AccessDecisionManager // interceptor.setAccessDecisionManager(customAccessDecisionManager); return interceptor; } }) ) // ... 其他配置(表单登录、CSRF等) ; return http.build(); } }

    效果:完成以上步骤后,您就可以通过管理界面(或直接操作数据库)动态地配置某个API接口(如创建文档的接口)允许哪些角色访问,而无需修改@PreAuthorize注解或重新部署代码

方案二:结合方法级注解与动态数据源(更灵活)

如果您希望保留@PreAuthorize注解的灵活性,同时实现动态配置,可以创建一个自定义的权限评估器。

  1. 创建自定义权限表达式
    实现Spring Security的PermissionEvaluator接口或创建自定义的SPEL表达式函数。

    java

    @Component("docPermissionEvaluator") public class DocumentPermissionEvaluator { @Autowired private RoleConfigService roleConfigService; public boolean hasPermission(Authentication authentication, String resourceKey) { // 1. 获取当前用户的所有角色 Set<String> userRoles = authentication.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.toSet()); // 2. 根据 resourceKey(如 "CREATE_DOCUMENT"),从数据库查询允许的角色 Set<String> allowedRoles = roleConfigService.getAllowedRolesForResource(resourceKey); // 3. 判断用户角色与允许角色是否有交集 return !Collections.disjoint(userRoles, allowedRoles); } }
  2. 在配置中暴露Bean并用于SPEL
    在安全配置中暴露该评估器,并在@PreAuthorize注解中使用。

    java

    @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { @Autowired private DocumentPermissionEvaluator docPermissionEvaluator; @Override protected MethodSecurityExpressionHandler createExpressionHandler() { DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); // 注册自定义的权限评估器 expressionHandler.setPermissionEvaluator(docPermissionEvaluator); // 也可以将评估器直接注册为根对象,以便在SPEL中直接调用 expressionHandler.setRootObject(new SecurityExpressionRootMethods(docPermissionEvaluator)); return expressionHandler; } }

    然后,修改您的控制器方法注解:

    java

    @PostMapping @PreAuthorize("@docPermissionEvaluator.hasPermission(authentication, 'CREATE_DOCUMENT')") public Document createDocument(@RequestBody DocumentCreateCommand command) { // 权限逻辑由评估器动态决定 }

    效果:权限规则('CREATE_DOCUMENT'资源允许哪些角色)存储在数据库中,可通过管理界面配置

方案三:实现动态角色继承

如果您的需求包括角色之间的动态继承关系(例如,SENIOR_ADMIN自动拥有ADMIN的所有权限),可以使用Spring Security的RoleHierarchy

  1. 从数据库加载继承关系
    将角色继承关系(如ROLE_SENIOR_ADMIN > ROLE_ADMIN > ROLE_USER)存储在数据库中。

    java

    @Bean public RoleHierarchy roleHierarchy() { RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); // 从数据库或配置中心动态获取继承关系字符串 String hierarchy = roleService.getRoleHierarchyAsString(); roleHierarchy.setHierarchy(hierarchy); return roleHierarchy; }
  2. 在安全配置中启用
    配置了RoleHierarchyBean后,Spring Security在检查hasRole('ADMIN')时,会自动认为拥有SENIOR_ADMIN角色的用户也满足条件

总结与建议

  • 对于您的具体场景(使@PostMapping接口的角色可配置),方案一(动态URL权限)是最直接、最符合Spring Security原生命令式配置风格的解决方案,它彻底将角色与接口的绑定关系外置。
  • 方案二(自定义表达式)提供了更细粒度的控制,适合资源键(resourceKey)与业务逻辑紧密耦合的复杂场景。
  • 方案三(角色继承)可以作为上述方案的补充,用于简化角色权限的管理,避免为高级角色重复配置所有低级角色的权限。
  • 性能优化:无论采用哪种方案,频繁查询数据库都会成为性能瓶颈。务必在用户登录认证成功后,将其角色/权限信息缓存起来(如存储在Redis或SecurityContext中),在权限校验时直接从缓存读取,避免每次请求都访问数据库。
  • 管理界面:为了实现真正的“可配置”,您需要配套开发一个角色和权限的管理界面,允许系统管理员通过UI界面(而非直接操作数据库)来为用户分配角色、为接口(资源)绑定角色。

通过实施上述任一方案,您就可以将代码中硬编码的角色依赖解耦,实现灵活、可动态配置的权限管理系统。

这是ai给我们的回答,你可以看到ai给了我们三种方案,这也是我将的在这个时代,在ai能够协助我们完成大部分事情的情况下对我们提出的新的考验,能够识别和判断ai给的东西是否合理是否能够有更好的方案,这不是单单代码能力要求,是对业务理解,代码能力,架构能力的综合考验。ai确实能够帮我们写代码,但是现阶段做最终决策的依然是人,人的决策能力决定了最终结果的上限。那么作为一个水平不高的人,我的选择定然是第一种,为什么因为我就见过第一种,当然我鼓励我的朋友们去三种都实现,毕竟这样才能真正对比出不同方案的优劣,而且在这个环境下,给了我们试错的资本毕竟不用自己写。但是在完成本章内容后我也会为大家完成这项工作,但是纸上得来终觉浅。那么我们后续再见

http://www.jsqmd.com/news/672255/

相关文章:

  • 如何免费生成专业条码:Libre Barcode开源字体终极指南
  • NineData亮相香港国际创科展InnoEX 2026,以AI加速布局全球市场
  • 从UML到SysML:给软件工程师的系统思维升级指南(含实战案例拆解)
  • 使用Python版LangChain调用外部函数实战:实现智能天气查询
  • intv_ai_mk11惊艳案例:用‘分点说明’指令生成直播复盘报告,覆盖数据/话术/节奏
  • D3KeyHelper:暗黑3玩家的智能操作助手,让技能循环自动化
  • 【STILT工具】ICOS 综合碳观测系统提供的 STILT Footprint 在线分析系统
  • 蓝桥杯CT107D开发板实战:用PCF8591芯片和光敏电阻DIY一个简易光照计
  • 【广西大学主办 | ACM出版(ISBN号: 979-8-4007-2349-0),往届已于会后3个月见刊,见刊后1个月检索 | 设评优评奖】第六届物联网与机器学习国际会议 (IoTML 2026)
  • 如何在5分钟内掌握PPTist:免费开源在线PPT制作工具的终极指南
  • 别只盯着IDE!RAD Studio 11升级前,先搞定你的数据库和部署环境(InterBase实战)
  • 深度解锁xrdp:构建企业级Linux远程桌面解决方案的实战指南
  • 2026玻璃门深度选型指南:如何匹配最佳玻璃解决方案? - 速递信息
  • Loom虚拟线程响应式项目上线前必检11项配置(含GC调优、Reactor资源泄漏防护、TraceID透传配置)
  • 从公式到仿真:DFIG风机MPPT控制的建模与实现
  • OpenClaw人人养虾:音频与语音
  • 93、快速筛选数据
  • JavaQuestPlayer:终极QSP游戏引擎与开发平台完整指南
  • NaViL-9B部署详解:双24GB显卡PCIe带宽优化与NVLink配置建议
  • Mobilerun架构深度解析:基于LLM的多Agent移动设备自动化框架设计
  • 5分钟快速部署:打造你的专属AI中医助手——仲景中医大语言模型实战指南
  • LangGraph CLI实战:5分钟搞定Python 3.11环境下的本地服务器部署(含常见错误排查)
  • 防脱洗发水怎么选?为什么劝你把“乌诺地尔”加入成分清单 - 速递信息
  • Dify金融合规配置实战指南:从零搭建符合银保监2024新规的AI应用流水线
  • 重返未来1999自动化助手M9A:如何轻松解放双手的终极指南
  • 华硕笔记本轻量化控制神器:G-Helper完全指南,告别臃肿的奥创中心
  • 如何免费使用多平台音乐聚合播放器:完整开源工具使用指南
  • 全新升级版H5封装分发平台|支持安卓APK与iOS A一键打包+免签分发
  • 官方认证|2026年国内五大正规助眠草本枕公司 / 批发厂排名,四川等地可参考,成都晓梦纺织品有限公司综合实力遥遥领先 - 十大品牌榜
  • 别急着看P控制图!用Minitab做二项分布能力分析前,先搞定这3个数据坑