上一篇博客中讲到了Shiro的登录功能,这篇讲讲Shiro的角色和权限
在Shiro中,一个用户可以有多种角色,一种角色可以有多种权限
在执行某些行为前时,我们既可以判断是否是该角色也可以判断是否拥有该权限
下面展示一个简单的例子
POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jk.shiroLearning</groupId>
<artifactId>chapter2</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<version-slf4j>1.6.6</version-slf4j>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${version-slf4j}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${version-slf4j}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<!--slf4j-log4j12 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<!--shiro核心包-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
</dependencies>
</project>
同之前一样
Shiro.ini
[users]
#帐号=密码,角色1,角色2……
jack=123456,role1,role2
[roles]
#对资源user拥有create、update权限,*代表任意,可在对象:行为:实例中替换
role1=user:create,user:update:*
#对资源user的1实例拥有delete权限
role2=user:delete:1
验证角色和权限
public class RoleAndPermissionTest {
@Test
public void main(){
//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
Factory<SecurityManager> factory =
new IniSecurityManagerFactory("classpath:shiro.ini");
//2、得到SecurityManager实例 并绑定给SecurityUtils
org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("jack", "123456");
try {
//4、登录,即身份验证
subject.login(token);
//判断是否有角色,没有则会抛出异常
subject.checkRole("role1");
//判断是否有权限,没有则会抛出异常
subject.checkPermission("user:update:1");
//判断是否有角色
System.out.println(subject.hasRole("role1"));
System.out.println(subject.hasRole("role2"));
System.out.println(subject.hasRole("role3"));
//判断有权限
System.out.println(subject.isPermitted("user:update:1"));
System.out.println(subject.isPermitted("user:delete:2"));
} catch (AuthenticationException e) {
//5、身份验证失败
e.printStackTrace();
}
System.out.println(subject.isAuthenticated());
//6、退出
subject.logout();
}
}
如果不想把用户信息,角色写死在配置文件里怎么办?这时就需要一个继承自AuthorizingRealm的类来实现认证的授权
自定义Realm
public class MyRealm extends AuthorizingRealm {
//授权,调用checkRole/checkPermission/hasRole/isPermitted都会执行该方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//可通过不同principal赋予不同权限
if (principals.getPrimaryPrincipal().equals("jack")){
//授予角色role1和role2
authorizationInfo.addRole("role1");
authorizationInfo.addRole("role2");
//授予对user任何行为任何实例的权限
authorizationInfo.addObjectPermission(new WildcardPermission("user:*"));
//等同于
//authorizationInfo.addStringPermission("user:*");
}
return authorizationInfo;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String)token.getPrincipal(); //得到用户名
String password = new String((char[])token.getCredentials()); //得到密码
if(!"jack".equals(username)) {
throw new UnknownAccountException(); //如果用户名错误
}
if(!"123456".equals(password)) {
throw new IncorrectCredentialsException(); //如果密码错误
}
//如果身份认证验证成功,返回一个AuthenticationInfo实现;
return new SimpleAuthenticationInfo(username, password, getName());
}
}
shiro-realm.ini
[main]
#自定义authorizer
authorizer=org.apache.shiro.authz.ModularRealmAuthorizer
securityManager.authorizer=$authorizer
#自定义realm 一定要放在securityManager.authorizer赋值之后(因为调用setRealms会将realms设置给authorizer,并给各个Realm设置permissionResolver和rolePermissionResolver)
realm=com.jk.realm.MyRealm
securityManager.realms=$realm
验证角色和权限
public class RealmTest {
@Test
public void main(){
//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
Factory<SecurityManager> factory =
new IniSecurityManagerFactory("classpath:shiro-realm.ini");
//2、得到SecurityManager实例 并绑定给SecurityUtils
org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("jack", "123456");
try {
//4、登录,即身份验证
subject.login(token);
//判断是否有角色,没有则会抛出异常
subject.checkRole("role1");
//判断是否有权限,没有则会抛出异常
subject.checkPermission("user:update:1");
//判断是否有角色
System.out.println(subject.hasRole("role1"));
System.out.println(subject.hasRole("role2"));
System.out.println(subject.hasRole("role3"));
//判断有权限
System.out.println(subject.isPermitted("user:update:1"));
System.out.println(subject.isPermitted("user:delete:2"));
} catch (AuthenticationException e) {
//5、身份验证失败
e.printStackTrace();
}
System.out.println(subject.isAuthenticated());
//6、退出
subject.logout();
}
}
网友评论