赞
踩
用户 -> 角色 -> 菜单 三者之间关联, 3张单表+2张关联表
Spring Security + Token
(不使用jwt是因为jwt无状态, 没法登出, 只能过期登出. 而token 存表可以)
使用流程:
登录 -> 拿到token -> 访问接口带上token
Controller 入口
cn.iocoder.yudao.module.system.controller.admin.auth.AuthController#login
流程
表名
流程
表名
前端调用其它接口,需要在请求头带上 Token 进行访问
Authorization: Bearer d2a3cdbc6c53470db67a582bd115103f
后端的过滤器:
cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter
流程:
① 基于【权限标识】的权限控制
权限标识,对应 system_menu 表的 permission 字段,推荐格式为 {系统}:{模块}:{操作},例如说 system:admin:add 标识 system 服务的添加管理员
// 符合 system:user:list 权限要求
@PreAuthorize("@ss.hasPermission('system:user:list')")
// 符合 system:user:add 或 system:user:edit 权限要求即可
@PreAuthorize("@ss.hasAnyPermissions('system:user:add,system:user:edit')")
② 基于【角色标识】的权限控制
权限标识,对应 system_role 表的 code 字段, 例如说 super_admin 超级管理员、tenant_admin 租户管理员
// 属于 user 角色
@PreAuthorize("@ss.hasRole('user')")
// 属于 user 或者 admin 之一
@PreAuthorize("@ss.hasAnyRoles('user,admin')")
原理:
调用beanName为ss的方法
YudaoSecurityAutoConfiguration里可以看到
@Bean("ss") // 使用 Spring Security 的缩写,方便使用
public SecurityFrameworkService securityFrameworkService(PermissionApi permissionApi) {
return new SecurityFrameworkServiceImpl(permissionApi);
}
一层一层走下去, 发现最终是调用
cn.iocoder.yudao.module.system.service.permission.PermissionService
的实现类
hasPermission 和 hasAnyPermissions
流程 rbac 的用法
hasRole和hasAnyRoles
流程
自定义注解, 声明登录的用户才允许访问
cn.iocoder.yudao.framework.security.core.aop.PreAuthenticatedAspect
用aop实现
流程
AuthorizeRequestsCustomizer的实现
比如各个module里的XxxSecurityConfiguration的配置的bean, return new AuthorizeRequestsCustomizer(), 重写customize方法
可以看
cn.iocoder.yudao.module.infra.framework.security.config.SecurityConfiguration#authorizeRequestsCustomizer方法
@Bean("infraAuthorizeRequestsCustomizer") public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() { return new AuthorizeRequestsCustomizer() { @Override public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) { // Swagger 接口文档 registry.antMatchers("/v3/api-docs/**").permitAll() .antMatchers("/swagger-ui.html").permitAll() .antMatchers("/swagger-ui/**").permitAll() .antMatchers("/swagger-resources/**").anonymous() .antMatchers("/webjars/**").anonymous() .antMatchers("/*/api-docs").anonymous(); // 积木报表 registry.antMatchers("/jmreport/**").permitAll(); // Spring Boot Actuator 的安全配置 registry.antMatchers("/actuator").anonymous() .antMatchers("/actuator/**").anonymous(); // Druid 监控 registry.antMatchers("/druid/**").anonymous(); // Spring Boot Admin Server 的安全配置 registry.antMatchers(adminSeverContextPath).anonymous() .antMatchers(adminSeverContextPath + "/**").anonymous(); // 文件读取 registry.antMatchers(buildAdminApi("/infra/file/*/get/**")).permitAll(); } }; }
在 API 接口上添加 @PermitAll 注解
比如
cn.iocoder.yudao.module.member.controller.app.auth.AppAuthController
@PostMapping("/logout")
@PermitAll
@Operation(summary = "登出系统")
public CommonResult<Boolean> logout(HttpServletRequest request) {
String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader());
if (StrUtil.isNotBlank(token)) {
authService.logout(token);
}
return success(true);
}
cn.iocoder.yudao.framework.security.config.SecurityProperties
会解析到成员变量permitAllUrls里
yudao:
security:
permit-all-urls:
- /admin-ui/** # /resources/admin-ui 目录下的静态资源
- /admin-api/xxx/yyy
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。