Apache Shiro的起步和自定义Facroty以及自定义RolePermissionResolver

当前运行环境:eclipse 、shiro 1.4.1

1.配置依赖

<dependencies>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.9</version>
	</dependency>
	<dependency>
		<groupId>commons-logging</groupId>
		<artifactId>commons-logging</artifactId>
		<version>1.1.3</version>
	</dependency>
	<dependency>
		<groupId>org.apache.shiro</groupId>
		<artifactId>shiro-core</artifactId>
		<version>1.4.1</version>
	</dependency>
	<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-api</artifactId>
		<version>2.0.0-alpha1</version>
	</dependency>
	<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-simple</artifactId>
		<version>2.0.0-alpha1</version>
	</dependency>

</dependencies>

当前的shiro依赖于slf4j,没有slf4j的话就会报错!

2.开始简单的demo(ini配置文件版)

创建shiroIniApp类


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.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.apache.shiro.mgt.SecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ShiroIniApp 
{
    private Logger logger;
    private Factory<SecurityManager> factory;
    private SecurityManager securityManager;
    private Subject subject;
    private UsernamePasswordToken token;
    
    @Before
	public void init() {
    	logger = LoggerFactory.getLogger(ShiroIniApp.class);
    	//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
    	 factory =initSecurityManagerFactory();
        //2、得到SecurityManager实例 并绑定给SecurityUtils   
    	securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
        //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
        subject = SecurityUtils.getSubject();
        token = new UsernamePasswordToken("zhangsan", "123456");
    }
    
    public Factory<SecurityManager> initSecurityManagerFactory() {
		 return new IniSecurityManagerFactory("classpath:shiro.ini");
    }
    
    @Test
    public void testDefaultDemo() {
        try {
            //4、登录,即身份验证
            subject.login(token);
            logger.info("身份验证成功!");
        } catch (AuthenticationException e) {
            //5、身份验证失败
        	 logger.info("身份验证失败!");
        }
        Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录
        
        //判断当前用户是否具有admin角色      
        boolean hasAdminRole = subject.hasRole("user");
        logger.info("是否具有user权限:"+hasAdminRole);
        if(hasAdminRole) {
        	boolean hasAllPermission = subject.isPermitted("update");
        	logger.info("是否拥有update权限:"+hasAllPermission);
        }
        //6、退出
        subject.logout();
    }

当前的shiro.ini文件的内容为:

[users]
zhangsan = 123456,user,guest
admin = 123456,admin

[roles]
admin = *
guest = select
user = select,update,add

3.测试当前配置文件版的shiro

[main] INFO org.apache.shiro.session.mgt.AbstractValidatingSessionManager - Enabling session validation scheduler...
[main] INFO com.hy.shiro.demo.ShiroIniApp - 身份验证成功!
[main] INFO com.hy.shiro.demo.ShiroIniApp - 是否具有user权限:true
[main] INFO com.hy.shiro.demo.ShiroIniApp - 是否拥有update权限:true

结果成功!

但是当前的类IniSecurityManagerFactory已经被废弃,下面定义管理工厂

4.创建自定义的Factory和RolePermissionResolver

1.通过查看源码发现当前的Facorty接口只有一个方法:getInstance()
所以决定自己实现这个接口

2.所以泛型的类型就是org.apache.shiro.mgt.SecurityManager这个类

3.查看org.apache.shiro.mgt.SecurityManager这个类的源码和结构树

在这里插入图片描述

4.发现只有一个类DefaultSecurityManager所以直接返回这个类即可

5.查看当前DefaultSecurityManager的构造函数发现需要一个或者多个Realm
再次查看Realm的机构树

在这里插入图片描述
6.查看结构树,我选择的是TextConfigurationRealm,而且这个类中有一个addAccount和setRolePermissionResolver方法

7.而RolePermissionResolver中的为接口,直接实现即可

8.通过RolePermissionResolver接口中的方法发现需要Permission,所以查看Permission结构树:

在这里插入图片描述
这里的Permission实现类就三个,从字面意思可看出AllPermission表示*(拥有所有权限),WildcardPermission(通配符权限),DomainPermission(域权限),这里可以直接使用WildcardPermission即可

通过debug发现解析ini文件生成的也是WildcardPermission这个类

以上的问题全部解决所以实现代码如下:


import java.util.Arrays;
import java.util.List;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.text.TextConfigurationRealm;
import org.apache.shiro.util.Factory;

public class MyShiroFacroty implements Factory<org.apache.shiro.mgt.SecurityManager> {
	//创建全局的权限解析器
	MyRolePermissionResolver resolver=new MyRolePermissionResolver();
	//创建默认的校验管理器
	DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
	
	public SecurityManager getInstance() {
		//创建第一个用户:admin ,密码为123456 ,拥有角色为admin
		TextConfigurationRealm realm1=new TextConfigurationRealm();
		realm1.addAccount("admin", "123456","admin");
		realm1.setRolePermissionResolver(resolver);//设置角色权限解析器
		
		//创建第二个用户为zhangsan 密码为 123456 ,拥有角色:user、guest
		TextConfigurationRealm realm2=new TextConfigurationRealm();
		realm2.addAccount("zhangsan", "123456","user","guest");
		realm2.setRolePermissionResolver(resolver);//设置角色权限解析器
		
		Realm[] realms= {realm1,realm2};
		List<Realm> asList = Arrays.asList(realms);
		defaultSecurityManager.setRealms(asList);//向校验管理器中设置当前的用户
		return defaultSecurityManager;
	}

}

当前的权限解析类如下:

import java.util.Arrays;
import java.util.Collection;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.permission.AllPermission;
import org.apache.shiro.authz.permission.RolePermissionResolver;
import org.apache.shiro.authz.permission.WildcardPermission;
/**
 * @description 自定义角色权限解析器
 * @author hy
 * @date 2019-10-03
 */
public class MyRolePermissionResolver implements RolePermissionResolver {
	//实现通过角色解析权限的过程
	public Collection<Permission> resolvePermissionsInRole(String roleString) {
		Permission[] permissions= null;
		if("admin".equalsIgnoreCase(roleString)) {
			//AllPermission表示具有所有的权限
			permissions=new Permission[]{new AllPermission()};
		}else if("user".equalsIgnoreCase(roleString)) {
			//通过查看发现应该创建wildCardPermission这个类的实例,并向parts中添加权限
			permissions=new Permission[]{
					new WildcardPermission("select,update,add")
			};
			//通过查看源码发现当前的WildcardPermission中的有参构造函数中向其中添加的字符会转换成parts字符集合
		}else if("guest".equalsIgnoreCase(roleString)) {
			permissions=new Permission[]{
					new WildcardPermission("select")
			};
		}
		return Arrays.asList(permissions);
	}

}

5.测试自定义Facroty以及自定义RolePermissionResolver

直接将其中的initFactory方法换成

 
   public Factory<SecurityManager> initSecurityManagerFactory() {
	/* return new IniSecurityManagerFactory("classpath:shiro.ini"); */
	 return new MyShiroFacroty(); 
   }

结果:

[main] INFO org.apache.shiro.session.mgt.AbstractValidatingSessionManager - Enabling session validation scheduler...
[main] INFO com.hy.shiro.demo.ShiroIniApp - 身份验证成功!
[main] INFO com.hy.shiro.demo.ShiroIniApp - 是否具有user权限:true
[main] INFO com.hy.shiro.demo.ShiroIniApp - 是否拥有update权限:true

与上面完全一致!

6.总结

1.使用配置文件编写shiro.ini的时候需要

  1. 在[users]下使用用户名=密码,角色1,角色2...
  2. 在[roles]下使用角色1=权限1,权限2...

2.在自定义的Factory中需要

  1. 使用默认的校验管理器(DefaultSecurityManager)TextConfigurationRealm来创建用户名、密码和权限
  2. 需要使用WildcardPermission来创建Permission(权限)

3.当前的shiro通过SecurityManager来管理校验通过Subject来进行每一次操作,通过创建token来管理用户登录的用户名和密码

4.通过使用发现当前的Shiro框架相对于Spring Security来说,继承层次比较简单,对象关系简单,容易上手!

以上纯属个人见解,如有问题请联系本人!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值