专注Java教育14年 全国咨询/投诉热线:400-8080-105
动力节点LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 Shiro配置文件详解

Shiro配置文件详解

更新时间:2022-11-21 08:58:00 来源:动力节点 浏览954次

Shiro 旨在在任何环境中工作,从简单的命令行应用程序到最大的企业集群应用程序。由于环境的这种多样性,因此有许多适合配置的配置机制。

编程配置

创建 SecurityManager 并使其对应用程序可用的绝对最简单的方法是创建一个org.apache.shiro.mgt.DefaultSecurityManager并在代码中连接它。例如:

Realm realm = //instantiate or acquire a Realm instance.  We'll discuss Realms later.
SecurityManager securityManager = new DefaultSecurityManager(realm);
//Make the SecurityManager instance available to the entire application via static memory:
SecurityUtils.setSecurityManager(securityManager);

SecurityManager 对象图

Shiro 的SecurityManager实现本质上是嵌套的安全特定组件的模块化对象图。因为它们也是 JavaBeans 兼容的,所以您可以调用任何嵌套组件getter和setter方法来配置SecurityManager及其内部对象图。

例如,如果你想将SecurityManager实例配置为使用自定义SessionDAO来自定义Session Management,你可以SessionDAO直接使用嵌套的 SessionManagersetSessionDAO方法进行设置:

...
DefaultSecurityManager securityManager = new DefaultSecurityManager(realm);
SessionDAO sessionDAO = new CustomSessionDAO();
((DefaultSessionManager)securityManager.getSessionManager()).setSessionDAO(sessionDAO);
...

使用直接方法调用,您可以配置“SecurityManager”对象图的任何部分。

但是,就像编程定制一样简单,它并不代表大多数现实世界应用程序的理想配置。程序化配置可能不适合您的应用程序有以下几个原因:

它要求您了解并实例化直接实现。如果您不必了解具体的实现以及在哪里可以找到它们,那就更好了。

由于 Java 的类型安全特性,您需要将通过get*方法获得的对象转换为它们的特定实现。如此多的转换是丑陋的、冗长的,并且将您与实现类紧密耦合。

SecurityUtils.setSecurityManager方法调用使实例化的实例SecurityManager成为一个 VM 静态单例,这对于许多应用程序来说很好,但如果在同一个 JVM 上运行多个启用 Shiro 的应用程序,则会导致问题。如果实例是应用程序单例而不是静态内存引用,则可能会更好。

每次您想要更改 Shiro 配置时,它都要求您重新编译您的应用程序。

然而,即使有这些警告,直接编程操作方法在内存受限的环境中仍然很有价值,例如智能手机应用程序。如果您的应用程序不在内存受限的环境中运行,您会发现基于文本的配置更易于使用和阅读。

INI配置

大多数应用程序反而受益于基于文本的配置,这些配置可以独立于源代码进行修改,甚至让那些不熟悉 Shiro 的 API 的人更容易理解。

为确保通用的基于文本的配置机制可以在所有环境中工作且第三方依赖性最小,Shiro 支持INI 格式来构建SecurityManager对象图及其支持组件。INI 易于阅读、易于配置、设置简单,非常适合大多数应用程序。

从 INI 创建一个 SecurityManager

下面是两个如何基于 INI 配置构建 SecurityManager 的示例。

来自 INI 资源的 SecurityManager

我们可以从 INI 资源路径创建 SecurityManager 实例。资源可以从文件系统、类路径或分别以 、 或 为前缀的file:URLclasspath:获取url:。此示例使用 a从类路径的根目录中Factory提取文件并返回实例:shiro.iniSecurityManager

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.util.Factory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.config.IniSecurityManagerFactory;
...
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);

来自 INI 实例的 SecurityManager

如果需要,也可以通过org.apache.shiro.config.Ini类以编程方式构建 INI 配置。Ini 类的功能与 JDK 类类似java.util.Properties,但还支持按部分名称进行分段。

例如:

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.util.Factory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.config.Ini;
import org.apache.shiro.config.IniSecurityManagerFactory;
...
Ini ini = new Ini();
//populate the Ini instance as necessary
...
Factory<SecurityManager> factory = new IniSecurityManagerFactory(ini);
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);

现在我们知道如何SecurityManager从 INI 配置构建,让我们来看看如何定义 Shiro INI 配置。

INI 部分

INI 基本上是一个文本配置,由按唯一命名的部分组织的键/值对组成。密钥仅在每个部分是唯一的,而不是在整个配置中(与 JDK Properties不同)。然而,每个部分都可以看作是一个单独的Properties定义。

注释行可以以 Octothorpe(# - 又名“井号”、“井号”或“数字”符号)或分号 (';') 开头

以下是 Shiro 理解的部分示例:

# =======================
# Shiro INI configuration
# =======================
[main]
# Objects and their properties are defined here,
# Such as the securityManager, Realms and anything
# else needed to build the SecurityManager
[users]
# The 'users' section is for simple deployments
# when you only need a small number of statically-defined
# set of User accounts.
[roles]
# The 'roles' section is for simple deployments
# when you only need a small number of statically-defined
# roles.
[urls]
# The 'urls' section is used for url-based security
# in web applications.  We'll discuss this section in the
# Web documentation

[Main]

该[main]部分是您配置应用程序SecurityManager实例及其任何依赖项(例如Realm)的地方。

使用 INI 配置对象实例(如 SecurityManager 或其任何依赖项)听起来很困难,我们只能使用名称/值对。但是通过对对象图的一些约定和理解,您会发现您可以做很多事情。Shiro 使用这些假设来启用简单但相当简洁的配置机制。

我们经常喜欢将这种方法称为“穷人的”依赖注入,虽然不如成熟的 Spring/Guice/JBoss XML 文件那么强大,但您会发现它可以完成很多工作而没有太多复杂性。当然那些其他配置机制也可用,但它们不是使用 Shiro 所必需的。

为了激发您的胃口,这里有一个有效[main]配置的示例。我们将在下面详细介绍它,但您可能会发现仅凭直觉您就已经了解了很多正在发生的事情:

[main]
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
myRealm = com.company.security.shiro.DatabaseRealm
myRealm.connectionTimeout = 30000
myRealm.username = jsmith
myRealm.password = secret
myRealm.credentialsMatcher = $sha256Matcher
securityManager.sessionManager.globalSessionTimeout = 1800000

定义对象

考虑以下[main]部分片段:

[main]
myRealm = com.company.shiro.realm.MyRealm
...

此行实例化一个新的对象实例,com.company.shiro.realm.MyRealm并使该对象在myRealm名称下可用,以供进一步参考和配置。

如果实例化的对象实现了org.apache.shiro.util.Nameable接口,则将在名称为值(在本例中)Nameable.setName的对象上调用该方法。myRealm

设置对象属性

原始值

只需使用等号即可分配简单的原始属性:

...
myRealm.connectionTimeout = 30000
myRealm.username = jsmith
...

这些配置行转化为方法调用:

...
myRealm.setConnectionTimeout(30000);
myRealm.setUsername("jsmith");
...

在幕后,Shiro 在设置这些属性时默认使用 Apache Commons BeanUtils来完成所有繁重的工作。因此,虽然 INI 值是文本,但 BeanUtils 知道如何将字符串值转换为适当的原始类型,然后调用相应的 JavaBeans setter 方法。

======= 参考值

如果您需要设置的值不是原始值,而是另一个对象怎么办?那么,您可以使用美元符号 ($) 来引用先前定义的实例。例如:

...
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
...
myRealm.credentialsMatcher = $sha256Matcher
...

这只是定位由名称sha256Matcher定义的对象,然后使用 BeanUtils 在myRealm实例上设置该对象(通过调用myRealm.setCredentialsMatcher(sha256Matcher)方法)。

嵌套属性

使用 INI 行等号左侧的点分符号,您可以遍历对象图以到达您要设置的最终对象/属性。例如,此配置行:

...
securityManager.sessionManager.globalSessionTimeout = 1800000
...

将(通过 BeanUtils)翻译成以下逻辑:

securityManager.getSessionManager().setGlobalSessionTimeout(1800000);

图形遍历可以根据需要深入:object.property1.property2…​.propertyN.value = blah

字节数组值

因为原始字节数组不能以文本格式本地指定,所以我们必须使用字节数组的文本编码。这些值可以指定为 Base64 编码字符串(默认值)或十六进制编码字符串。默认是 Base64,因为 Base64 编码需要更少的实际文本来表示值——它有更大的编码字母表,这意味着你的标记更短(文本配置更好一点)。

# The 'cipherKey' attribute is a byte array. By default, text values # for all byte array properties are expected to be Base64 encoded: securityManager.rememberMeManager.cipherKey = kPH+bIxk5D2deZiIxcaaaA== ...

但是,如果您更喜欢使用十六进制编码,则必须在字符串标记前加上0x('zero' 'x'):

securityManager.rememberMeManager.cipherKey = 0x3707344A4093822299F31D008

集合属性

列表、集合和映射可以像任何其他属性一样设置 - 直接设置或作为嵌套属性设置。对于集合和列表,只需指定一组以逗号分隔的值或对象引用。

比如一些SessionListeners:

sessionListener1 = com.company.my.SessionListenerImplementation
...
sessionListener2 = com.company.my.other.SessionListenerImplementation
...
securityManager.sessionManager.sessionListeners = $sessionListener1, $sessionListener2

对于地图,您指定一个以逗号分隔的键值对列表,其中每个键值对由冒号“:”分隔

object1 = com.company.some.Class
object2 = com.company.another.Class
...
anObject = some.class.with.a.Map.property
anObject.mapProperty = key1:$object1, key2:$object2

在上面的例子中,引用的对象$object1将在 String key 下的 map 中key1,即map.get("key1")returns object1。您还可以使用其他对象作为键:

anObject.map = $objectKey1:$objectValue1, $objectKey2:$objectValue2
...

变量插值

您可以在定义值时使用变量插值。支持的类型是环境变量、系统属性和常量。

对于常量,使用${const:com.example.YourClass.CONSTANT_NAME},对于环境变量和系统属性,使用${ENV_VARIABLE_NAME}or ${system.property}。

系统属性和环境变量按该顺序查找。

${const:com.example.YourClass.CONSTANT_NAME:-default_value}默认值以, 或的形式被支持${VARIABLE_NAME:-default_value},例如:

这将被解释为myRealm.connectionTimeout = 3000好像没有定义系统属性或环境变量REALM_CONNECTION_TIMEOUT。

如果没有找到替换,定义将保持不变。

以上就是关于“Shiro配置文件详解”的介绍,大家如果想了解更多相关知识,可查看Shiro视频教程。动力节点在线学习教程,针对没有任何Java基础的读者学习,让你从入门到精通,主要介绍了一些Java基础的核心知识,让同学们更好更方便的学习和了解Java编程。

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>