05-自定义Realm授权(ssm+Shiro)
简介:
和认证的原理一样,授权也需要从数据库中获取权限数据,所以需要自定义授权的Realm,改写Realm的认证和授权方法。
一、创建自定义的Realm,CustomRealm.java【认证的代码和之前的认证一样】
package cn.itcast.shiro.realm;
import java.util.ArrayList;
import java.util.List;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
// 自定义Realm
public class CustomRealm extends AuthorizingRealm {
/**
* 认证
* token:用户输入的令牌,可以是字符串,也可以是对象
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
// 从token中获取用户名
String username = (String) token.getPrincipal();
// 根据用户输入的用户名从数据库中查找用户信息(密码),这里只是模拟的静态数据
// 如果查不到就返回null...
// 假设数据库中的用户名是PeterDB
if (!"zhang".equals(username)) {
return null; // 返回null之后,下面的代码都不执行
}
// 如果查到就返回password
String password = "123";
// 返回认证信息
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password, this.getName());
return simpleAuthenticationInfo;
}
// Realm的名称(自定义),可以不定义
@Override
public void setName(String name) {
super.setName("customRealm");
}
/**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
// 授权是在认证通过后的操作,principals是认证通过后返回的SimpleAuthenticationInfo对象的第一个参数
String username = (String) principals.getPrimaryPrincipal();
// 模拟数据库的静态数据(开发中要从数据库中获取)
List<String> permissions = new ArrayList<String>();
permissions.add("user:create"); // 添加用户
permissions.add("items:add"); // 添加商品
// 返回权限信息
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addStringPermissions(permissions);
return simpleAuthorizationInfo;
}
}
二、把自定义Realm注入到SecurityManager中,shiro-realm.ini
[main] # 自定义Realm customRealm=cn.itcast.shiro.realm.CustomRealm # 将自定义的Realm注入到SecurityManager中,这里相当于spring中的注入 securityManager.realms=$customRealm
三、测试代码,AuthorizationTest.java
package cn.itcast.shiro.authorization; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; import org.junit.Test; // 授权测试 public class AuthorizationTest { // 自定义Realm进行资源授权 @Test public void testAuthorizationCustomRealm() { // 准备工作 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini"); SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); Subject subject = SecurityUtils.getSubject(); // 先认证通过后才能进行授权操作 UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123"); try { subject.login(token); } catch (AuthenticationException e) { e.printStackTrace(); } System.out.println("认证结果:" + subject.isAuthenticated()); System.out.println("--------------------------------"); System.out.println("授权结果:"); // 授权 // 1.基于角色的授权,除了下面的方法,还有其他方法,比如hasAllRoles()等等,具体查看文档 boolean hasRole_role1 = subject.hasRole("role1"); System.out.println("是否拥有role1角色:" + hasRole_role1); boolean hasRole_role10 = subject.hasRole("role10"); System.out.println("是否拥有role10角色:" + hasRole_role10); // 2.基于资源的授权,除了下面的方法,还有其他方法,具体查看文档 boolean permitted_Usercreate = subject.isPermitted("user:create"); boolean permitted_UserAdd = subject.isPermitted("user:add"); System.out.println("是否拥有user:create权限:" + permitted_Usercreate); System.out.println("是否拥有user:add权限:" + permitted_UserAdd); // 具体资源,如果拥有user:create角色,就代表拥有user:create:*的角色 boolean permitted_001 = subject.isPermitted("user:create:001"); System.out.println("是否拥有user:create:001(新增001用户)的权限:" + permitted_001); } }
工程结构:
运行结果:
认证结果:true
--------------------------------
授权结果:
是否拥有role1角色:false
是否拥有role10角色:false
是否拥有user:create权限:true
是否拥有user:add权限:false
是否拥有user:create:001(新增001用户)的权限:true
-----------------------------------
授权过程:
1、执行subject.isPermitted("user:create")
2、securityManager通过ModularRealmAuthorizer进行授权
3、ModularRealmAuthorizer调用realm获取权限信息
4、ModularRealmAuthorizer再通过permissionResolver解析权限字符串,校验是否匹配