一、Permission字符串
1、格式
资源:权限:操作
(常用格式是:模块:功能:操作)
- 资源 :指系统中需要被保护的对象、数据或服务等。资源可以是一个统称,也可以是具体的对象。
- 权限 :指对资源所具备的操作或功能,用于限制对资源的访问和使用。权限可以是一个动词或描述性词语。需要准确表示权限的作用或功能。
- 操作:指执行某个权限对应的具体行为,如CRUD。
通配符(*
)表示一个或多个。
还可以使用简单的通配符,如
sys:user:*
,建议省略为sys:user
(分离前端不能使用星号写法)
举例1sys:user
将于sys:user
或sys:user:
开头的所有权限字符串匹配成功
举例2sys
将于sys
或sys:
开头的所有权限字符串匹配成功
2、具体示例
模块:功能:操作
例1:sys:user:edit
代表 系统模块:用户功能:编辑操作
例2:report:couponReceive:*
代表 报表模块:优惠券领取功能:所有操作
3、其他分隔符
-
使用"/"作为分隔符
一种层次结构路径,显示权限是如何在资源之间划分的。
例如,posts/view/read
-
使用"."作为分隔符
通常适用于具有明确定义的对象或资源层次结构的系统,使权限更像分层组件或命名空间。
例如,posts.view.read
疑惑:上面3种形式(:
,/
,.
),在实际开发中应该用那种分隔符?
回答:个人理解,用那种都行,主要根据系统最开始时怎么定义,想用那种都行。
二、认证授权的相关内容
1、权限与URI,以及URL的区别
- 权限(permission):在 其他分隔符 中,有用"/"作为分割符,与URL和URI的样式很相似,但它主要还是作为权限的字符串。
- URI:唯一标识一个资源。在filterChainDefinitionMap中,URI既可以是后端请求的地址,也可以是静态资源的路径。
URI通配符:
1.?
:匹配一个字符。【任意的一个字符】
2.*
:匹配零个或多个字符串。【任意的一个路径】
3.**
:匹配路径中的零个或多个路径。【任意路径及子路径】
注意:
上面写的是URI(统一资源标识符),不是URL(统一资源定位符),两者存在区别:
URL是一种具体的URI,它是URI的一个子集,它不仅唯一标识资源,而且还提供了定位该资源的信息。URI 是一种语义上的抽象概念,可以是绝对的,也可以是相对的,而URL则必须提供足够的信息来定位,是绝对的。
简单说:
URI:身份证号 (只能知道有这么个人,但具是谁不知道)
URL:身份证住址+姓名 (不仅具体知道这个人是谁,还能找到他)
只要能唯一表示资源的就是URI,在URI的基础上给出其资源的访问方式的就是URL。
以上参考:
URI和URL的区别与联系
在实际开发中,权限(permission)和URI是结合使用的。
@Bean
public FilterChainDefinitionMap createFilterChainDefinitionMap() {
Map<String, String> filterChainMap = new LinkedHashMap<>();
filterChainMap.put("/public/**", "anon");
filterChainMap.put("/admin/**", "authc,roles[admin]");
filterChainMap.put("/**", "authc");
return new DefaultFilterChainDefinitionMap(filterChainMap);
}
在上面的例子中,我们将 /public/**
路径下的 URI 设置为不需要认证即可访问(anon
),
将 /admin/**
路径下的 URI 设置为 需要认证 和拥有 admin
权限才能访问(authc,roles[admin]
),
将其他所有路径下的 URI 设置为需要认证才能访问(authc
)。
2、认证和授权过滤器名称
1.认证过滤器名称
anon
: 表示不需要登录,就可以访问资源user
: 表示必须用户登录后才能访问资源,当登入操作时不做检查()authc
: 表示需要登录认证才能访问资源,一般用于登录接口
2.授权过滤器名称
perms
:例如/public/**=perms[user:add:*]
;参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/public/**=perms["user:add:*,user:modify:*"]
,当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。roles
:例如/admin/**=roles[admin]
;参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如/admin/**=roles["admin,guest"]
,每个参数通过才算通过,相当于hasAllRoles()方法。
3、授权方式
主要有4种:
- 编程式:通过 if/else 代码块来完成。
- 注解式:通过在执行的方法上放置相应的注解来完成,没有权限则抛出相应异常。
- 视图页面: 在视图页面(Beetl/JSP)通过相应的标签完成。
- 基于URI拦截:根据URI匹配,决定访问权限。
下面主要介绍注解式和基于URI拦截。
1、编程式(具体到数据)
场景:编辑和审核共用一个资源,可以在资源内判断是否有审核权限,然后再去执行对应操作
具体应用例子:用户是否具有对列表中某一条或某一类数据进行操作的权限
Subject subject = UserUtils.getSubject();
subject.isAuthenticated(); // 是否身份验证授权通过
subject.isPermitted(permission); // 验证权限字符串
subject.isPermittedAll(permissions); // 验证权限字符串全部通过
subject.hasRole(roleIdentifier); // 验证是否有角色权限
2、注解式(细粒度)
场景:对 URL 资源、按钮 等操作进行权限过滤,如果用户跳过了界面验证,直接去访问 URL 地址也需要经过授权验证的。
例如:用户具有用户管理的权限(但没具体说明是管理哪些用户)
具体应用例子:当前用户是否具有添加用户的权限(是否能请求添加接口)
在Controller的方法上指定如下注解:
@RequiresPermissions (value={“sys:user:view”, “sys:user:edit”}, logical= Logical.OR)
:表示当前 Subject 需要权限 user:view 或 user:edit。@RequiresRoles(value={“admin”, “user”}, logical=Logical.AND)
:表示当前 Subject 需要角色 admin 和 user@RequiresAuthentication
:表示当前Subject已经通过login进行了身份验证;@RequiresUser
:表示当前 Subject 已经身份验证或者通过记住我登录的。@RequiresGuest
:表示当前Subject没有身份验证或通过记住我登录过,即是游客身份。
3、基于URI拦截(粗粒度)
场景:当不方便利用编程式、注解式等方式过滤权限时,可以使用 URI 控制权限,或全局控制某个 URI 地址的权限
例如:用户只允许修改部门A(不能修改B、C部门的用户)
具体应用例子:判断当前主体是否有权限访问某些页面
格式:
URI地址及通配符 = 过滤器名称(支持多个,用英文逗号分隔并加双引号)
以上权限过滤器定义配置,是依照由上到下的第一次匹配优先原则,优先匹配成功的URI优先受用,支持通配符。
三、补充:什么是粗颗粒和细颗粒权限?
- 粗颗粒:对资源类型的管理称为粗颗粒度权限控制,即只控制到菜单、按钮、方法。
- 细颗粒:对资源实例的控制称为细颗粒度权限管理,即控制到数据级别的权限。