验证
验证的目的是测试用户账号是否合法,通常是测试用户名和密码是否匹配。shiro的验证从Subject.login
方法开始。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@Test public void testAuth(){ IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager manager = factory.getInstance(); SecurityUtils.setSecurityManager(manager); Subject subject = SecurityUtils.getSubject(); try{ AuthenticationToken token = new UsernamePasswordToken("jack", "123"); subject.login(token); } catch (AuthenticationException e){ //验证失败 System.err.println("Username or Password invalid"); } //用户名和密码都匹配,验证成功 Assert.assertEquals(true, subject.isAuthenticated()); subject.logout(); } |
授权
授权是对用户权限的控制,shiro有两种授权方式,分别是基于角色的授权和基于实际权限的授权。前者又称为显式角色,后者又称为隐式角色。角色实际上是一堆权限的集合体,权限控制的是对资源的访问。
shiro中的资源可以是数据库内容,可以是打印机,可以是代码中的特定方法,可以是网页中的特定元素:例如菜单,按钮等等。
ini文件中的角色
1 2 3 4 5 6 7 |
[users] jack=123, admin tom=456, normal [roles] admin=user:create, user:update, user:delete normal=user:view, user:update |
ini文件中定义了两个角色:admin和normal,角色后面的字符串就是实际上的权限描述,shiro中的权限单纯是一个字符串,它可以是任意字符串,字符串内容最好可以描述清楚所控制的权限。
测试授权
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@Test public void testAuthor() { IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager manager = factory.getInstance(); SecurityUtils.setSecurityManager(manager); Subject subject = SecurityUtils.getSubject(); try { AuthenticationToken token = new UsernamePasswordToken("jack", "123"); subject.login(token); } catch (AuthenticationException e) { //验证失败 System.err.println("Username or Password invalid"); } //判断用户是否admin Assert.assertEquals(true, subject.hasRole("admin")); //判断用户是否拥有删除用户权限 Assert.assertEquals(true, subject.isPermitted("user:delete")); subject.logout(); } |
角色和权限
shiro中一个用户(Subject)可以分配多个角色,一个角色可以分配多个权限。
一个用户分配多个角色:
1 2 |
[users] jack=123, admin, normal |
jack除了是管理员还是普通用户。
权限通常是一个字符串,字符串中使用冒号和逗号进行语义分隔:冒号用来分隔资源和操作,多个操作使用逗号来划分。举个例子:
删除用户、点击打印按钮这两个动作都非常常见。
- 用户是资源,删除是操作
- 按钮是资源(通常表现为一个菜单),打印是操作
把这两个动作具体化为权限就是:user:delete、menu:print。
Subject对象提供了一系列的方法,用来检查用户是否特定的角色,或者用户是否拥有某个权限。
1 2 3 4 5 6 7 |
subject.isPermitted("user:delete"); subject.isPermitted("menu:print") subject.checkPermission("user:delete"); subject.checkPermission("menu:print"); //或者写在一句中 subject.checkPermissions("user:delete", "menu:print"); |
权限的简写
当用户拥有的权限类似的时候,可以使用下面的简写:
1 |
admin="user:create,update,delete" |
表示用户拥有user:create, user:update, user:delete权限。
简写的好处在于在判断用户权限的时候只需要一句话即可
1 |
subject.checkPermissions("user:create,update,delete"); |
需要特别注意的是:如果使用简写,ini文件中的权限必须使用引号" "
括起来,且逗号之间不能有空格。否则会解析不到权限。这种问题如果使用完整的写法则不全在。
在权限中使用通配符
通配符*
可以使用在权限字符串的资源或者操作中,代表所有资源或者所有操作。
例如:user:*、*:delete
前者表示所有的用户操作,后者表示对所有资源的删除操作。
ini文件:
1 2 3 4 5 |
[users] john=111,super [roles] super=user:* |
测试代码:
1 2 3 4 5 6 7 8 9 10 11 |
try { AuthenticationToken token = new UsernamePasswordToken("john", "111"); subject.login(token); } catch (AuthenticationException e) { //验证失败 System.err.println("Username or Password invalid"); } Assert.assertEquals(true, subject.hasRole("super")); Assert.assertEquals(true, subject.isPermitted("user:delete")); Assert.assertEquals(true, subject.isPermitted("user:update")); |
一个通配符匹配一个资源或者一个操作,多个资源需要多个通配符。
匹配资源
system:user:delete,system:user:update,system:user:create使用通配符如下:
*:*:delete, *:*:update, *:*:create
匹配操作
还是使用上面的权限作为例子,如果使用通配符匹配操作,则写法如下:
system:user:*
表示system:user资源的所有权限:create, update, delete
转载请注明:Pure nonsense » shiro验证和授权