×
Shiro 关于Shiro 简介Shiro 身份验证Shiro 授权Shiro InI 配置Shiro 编码加密Shiro RealmShiro Web 集成Shiro 拦截器机制Shiro JSP 标签Shiro 会话管理Shiro 缓存机制Shiro Spring 集成Shiro RememberMeShiro SSLShiro 单点登录Shiro 综合实例Shiro OAuth2Shiro 并发登录控制Shiro 动态 URLShiro 无状态 WebShiro 授予身份和切换身份Shiro 集成验证码Shiro 多项目Shiro 在线会话管理

Shiro InI 配置


之前章节我们已经接触过一些 INI 配置规则了,如果大家使用过如 Spring 之类的 IoC/DI 容器的话,Shiro 提供的 INI 配置也是非常类似的,即可以理解为是一个 IoC/DI 容器,但是区别在于它从一个根对象 securityManager 开始。

根对象 SecurityManager

从之前的 Shiro 架构图可以看出,Shiro 是从根对象 SecurityManager 进行身份验证和授权的;也就是所有操作都是自它开始的,这个对象是线程安全且真个应用只需要一个即可,因此 Shiro 提供了 SecurityUtils 让我们绑定它为全局的,方便后续操作。

因为 Shiro 的类都是 POJO 的,因此都很容易放到任何 IoC 容器管理。但是和一般的 IoC 容器的区别在于,Shiro 从根对象 securityManager 开始导航;Shiro 支持的依赖注入:public 空参构造器对象的创建、setter 依赖注入。

1、纯 Java 代码写法(com.github.zhangkaitao.shiro.chapter4.NonConfigurationCreateTest):

DefaultSecurityManager securityManager = new DefaultSecurityManager();
//设置authenticator
ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
securityManager.setAuthenticator(authenticator);
//设置authorizer
ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer();
authorizer.setPermissionResolver(new WildcardPermissionResolver());
securityManager.setAuthorizer(authorizer);
//设置Realm
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/shiro");
ds.setUsername("root");
ds.setPassword("");
JdbcRealm jdbcRealm = new JdbcRealm();
jdbcRealm.setDataSource(ds);
jdbcRealm.setPermissionsLookupEnabled(true);
securityManager.setRealms(Arrays.asList((Realm) jdbcRealm));
//将SecurityManager设置到SecurityUtils 方便全局使用
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
subject.login(token);
Assert.assertTrue(subject.isAuthenticated());

2、等价的 INI 配置(shiro-config.ini)

[main]
#authenticator
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
authenticationStrategy=org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy
authenticator.authenticationStrategy=$authenticationStrategy
securityManager.authenticator=$authenticator
#authorizer
authorizer=org.apache.shiro.authz.ModularRealmAuthorizer
permissionResolver=org.apache.shiro.authz.permission.WildcardPermissionResolver
authorizer.permissionResolver=$permissionResolver
securityManager.authorizer=$authorizer
#realm
dataSource=com.alibaba.druid.pool.DruidDataSource
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql://localhost:3306/shiro
dataSource.username=root
#dataSource.password=
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource=$dataSource
jdbcRealm.permissionsLookupEnabled=true
securityManager.realms=$jdbcRealm 

即使没接触过 IoC 容器的知识,如上配置也是很容易理解的:

  1. 对象名 = 全限定类名 相对于调用 public 无参构造器创建对象
  2. 对象名. 属性名 = 值 相当于调用 setter 方法设置常量值
  3. 对象名. 属性名 =$ 对象引用 相当于调用 setter 方法设置对象引用

3、Java 代码(com.github.zhangkaitao.shiro.chapter4.ConfigurationCreateTest)

Factory<org.apache.shiro.mgt.SecurityManager> factory =
         new IniSecurityManagerFactory("classpath:shiro-config.ini");
org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
//将SecurityManager设置到SecurityUtils 方便全局使用
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
subject.login(token);
Assert.assertTrue(subject.isAuthenticated());&nbsp;

如上代码是从 Shiro INI 配置中获取相应的 securityManager 实例:

  1. 默认情况先创建一个名字为 securityManager,类型为 org.apache.shiro.mgt.DefaultSecurityManager 的默认的 SecurityManager,如果想自定义,只需要在 ini 配置文件中指定 “securityManager=SecurityManager 实现类” 即可,名字必须为 securityManager,它是起始的根;
  2. IniSecurityManagerFactory 是创建 securityManager 的工厂,其需要一个 ini 配置文件路径,其支持 “classpath:”(类路径)、“file:”(文件系统)、“url:”(网络)三种路径格式,默认是文件系统;
  3. 接着获取 SecuriyManager 实例,后续步骤和之前的一样。

从如上可以看出 Shiro INI 配置方式本身提供了一个简单的 IoC/DI 机制方便在配置文件配置,但是是从 securityManager 这个根对象开始导航。

INI 配置

ini 配置文件类似于 Java 中的 properties(key=value),不过提供了将 key/value 分类的特性,key 是每个部分不重复即可,而不是整个配置文件。如下是 INI 配置分类:

[main]
#提供了对根对象securityManager及其依赖的配置
securityManager=org.apache.shiro.mgt.DefaultSecurityManager
…………
securityManager.realms=$jdbcRealm
[users]
#提供了对用户/密码及其角色的配置,用户名=密码,角色1,角色2
username=password,role1,role2
[roles]
#提供了角色及权限之间关系的配置,角色=权限1,权限2
role1=permission1,permission2
[urls]
#用于web,提供了对web url拦截相关的配置,url=拦截器[参数],拦截器
/index.html = anon
/admin/** = authc, roles[admin], perms["permission1"]

[main] 部分

提供了对根对象 securityManager 及其依赖对象的配置。

创建对象

securityManager=org.apache.shiro.mgt.DefaultSecurityManager

其构造器必须是 public 空参构造器,通过反射创建相应的实例。

常量值 setter 注入

dataSource.driverClassName=com.mysql.jdbc.Driver
jdbcRealm.permissionsLookupEnabled=true&nbsp;

会自动调用 jdbcRealm.setPermissionsLookupEnabled(true),对于这种常量值会自动类型转换。

对象引用 setter 注入

authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
authenticationStrategy=org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy
authenticator.authenticationStrategy=$authenticationStrategy
securityManager.authenticator=$authenticator&nbsp;

会自动通过 securityManager.setAuthenticator(authenticator) 注入引用依赖。

嵌套属性 setter 注入

securityManager.authenticator.authenticationStrategy=$authenticationStrategy

也支持这种嵌套方式的 setter 注入。

byte 数组 setter 注入

#base64 byte[]
authenticator.bytes=aGVsbG8=
#hex byte[]
authenticator.bytes=0x68656c6c6f&nbsp;

默认需要使用 Base64 进行编码,也可以使用 0x 十六进制。

Array/Set/List setter 注入

authenticator.array=1,2,3
authenticator.set=$jdbcRealm,$jdbcRealm&nbsp;

多个之间通过 “,” 分割。

Map setter 注入

authenticator.map=$jdbcRealm:$jdbcRealm,1:1,key:abc

即格式是:map=key:value,key:value,可以注入常量及引用值,常量的话都看作字符串(即使有泛型也不会自动造型)。

实例化 / 注入顺序

realm=Realm1
realm=Realm12
authenticator.bytes=aGVsbG8=
authenticator.bytes=0x68656c6c6f&nbsp; 

后边的覆盖前边的注入。

测试用例请参考配置文件 shiro-config-main.ini。

[users] 部分

配置用户名 / 密码及其角色,格式:“用户名 = 密码,角色 1,角色 2”,角色部分可省略。如:

[users]
zhang=123,role1,role2
wang=123&nbsp; 

密码一般生成其摘要 / 加密存储,后续章节介绍。

[roles] 部分

配置角色及权限之间的关系,格式:“角色 = 权限 1,权限 2”;如:

[roles]
role1=user:create,user:update
role2=*&nbsp;

如果只有角色没有对应的权限,可以不配 roles,具体规则请参考授权章节。

[urls] 部分

配置 url 及相应的拦截器之间的关系,格式:“url = 拦截器 [参数],拦截器 [参数],如:

[urls]
/admin/** = authc, roles[admin], perms["permission1"]&nbsp;

具体规则参见 web 相关章节。


分类导航

关注微信下载离线手册

bootwiki移动版 bootwiki
(群号:472910771)