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解析权限字符串,校验是否匹配

 

posted @ 2017-07-23 16:10  半生戎马,共话桑麻、  阅读(199)  评论(0)    收藏  举报
levels of contents