forked from apache/shiro-site
-
Notifications
You must be signed in to change notification settings - Fork 0
/
configuration.md.vtl
491 lines (335 loc) · 24.3 KB
/
configuration.md.vtl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
<a name="Configuration-ApacheShiroConfiguration"></a>
Apache Shiro Configuration
==========================
* [Programmatic Configuration](#Configuration-ProgrammaticConfiguration)
* [SecurityManager Object Graph](#Configuration-SecurityManagerObjectGraph)
* [INI Configuration](#Configuration-INIConfiguration)
* [Creating a SecurityManager from INI](#Configuration-CreatingaSecurityManagerfromINI)
* [SecurityManager from an INI resource](#Configuration-SecurityManagerfromanINIresource)
* [SecurityManager from an INI instance](#Configuration-SecurityManagerfromanINIinstance)
* [INI Sections](#Configuration-INISections)
* [`[main]`](#Configuration-%5Cmain%5C)
* [Defining an object](#Configuration-Defininganobject)
* [Setting object properties](#Configuration-Settingobjectproperties)
* [Primitive Values](#Configuration-PrimitiveValues)
* [Reference Values](#Configuration-ReferenceValues)
* [Nested Properties](#Configuration-NestedProperties)
* [Byte Array Values](#Configuration-ByteArrayValues)
* [Collection Properties](#Configuration-CollectionProperties)
* [Considerations](#Configuration-Considerations)
* [Order Matters](#Configuration-OrderMatters)
* [Overriding Instances](#Configuration-OverridingInstances)
* [Default SecurityManager](#Configuration-DefaultSecurityManager)
* [`[users]`](#Configuration-%5Cusers%5C)
* [Line Format](#Configuration-LineFormat)
* [Encrypting Passwords](#Configuration-EncryptingPasswords)
* [`[roles]`](#Configuration-%5Croles%5C)
* [Line Format](#Configuration-LineFormat)
* [`[urls]`](#Configuration-%5Curls%5C)
Shiro is designed to work in any environment, from simple command-line applications to the largest enterprise clustered applications. Because of this diversity of environments, there are a number of configuration mechanisms that are suitable for configuration. This section covers the configuration mechanisms that are supported by Shiro core only.
#tip('Many Configuration Options', 'Shiro''s <code>SecurityManager</code> implementations and all supporting components are all JavaBeans compatible. This allows Shiro to be configured with practically any configuration format such as regular Java, XML (Spring, JBoss, Guice, etc), <a class="external-link" href="http://www.yaml.org/" rel="nofollow">YAML</a>, JSON, Groovy Builder markup, and more.')
<a name="Configuration-ProgrammaticConfiguration"></a>
Programmatic Configuration
--------------------------
The absolute simplest way to create a SecurityManager and make it available to the application is to create an `org.apache.shiro.mgt.DefaultSecurityManager` and wire it up in code. For example:
``` java
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);
```
Surprisingly, after only 3 lines of code, you now have a fully functional Shiro environment suitable for many applications. How easy was that!?
<a name="Configuration-SecurityManagerObjectGraph"></a>
#[[###SecurityManager Object Graph]]#
As discussed in the [Architecture](architecture.html "Architecture") chapter, Shiro's `SecurityManager` implementations are essentially a modular object graph of nested security-specific components. Because they are also JavaBeans-compatible, you can call any of the nested components `getter` and `setter` methods to configure the `SecurityManager` and its internal object graph.
For example, if you wanted to configure the `SecurityManager` instance to use a custom `SessionDAO` to customize [Session Management](session-management.html "Session Management"), you could set the `SessionDAO` directly with the nested SessionManager's `setSessionDAO` method:
``` java
...
DefaultSecurityManager securityManager = new DefaultSecurityManager(realm);
SessionDAO sessionDAO = new CustomSessionDAO();
((DefaultSessionManager)securityManager.getSessionManager()).setSessionDAO(sessionDAO);
...
```
Using direct method invocations, you can configure any part of the `SecurityManager`'s object graph.
But, as simple as programmatic customization is, it does not represent the ideal configuration for most real world applications. There are a few reasons why programmatic configuration may not be suitable for your application:
* It requires you to know about and instantiate a direct implementation. It would be nicer if you didn't have to know about concrete implementations and where to find them.
* Because of Java's type-safe nature, you're required to cast objects obtained via `get*` methods to their specific implementation. So much casting is ugly, verbose, and tightly-couples you to implementation classes.
* The `SecurityUtils.setSecurityManager` method call makes the instantiated `SecurityManager` instance a VM static singleton, which, while fine for many applications, would cause problems if more than one Shiro-enabled application was running on the same JVM. It could be better if the instance was an application singleton, but not a static memory reference.
* It requires you to recompile your application every time you want to make a Shiro configuration change.
However, even with these caveats, the direct programmatic manipulation approach could still be valuable in memory-constrained environments, like smart-phone applications. If your application does not run in a memory-constrained environment, you'll find text-based configuration to be easier to use and read.
<a name="Configuration-INIConfiguration"></a>
INI Configuration
-----------------
Most applications instead benefit from text-based configuration that could be modified independently of source code and even make things easier to understand for those not intimately familiar with Shiro's APIs.
To ensure a common-denominator text-based configuration mechanism that can work in all environments with minimal 3rd party dependencies, Shiro supports the [INI format](https://en.wikipedia.org/wiki/INI_file) to build the `SecurityManager` object graph and its supporting components. INI is easy to read, easy to configure, and is simple to set-up and suits most applications well.
<a name="Configuration-CreatingaSecurityManagerfromINI"></a>
#[[###Creating a SecurityManager from INI]]#
Here are two examples of how to build a SecurityManager based on INI configuration.
<a name="Configuration-SecurityManagerfromanINIresource"></a>
#[[####SecurityManager from an INI resource]]#
We can create the SecurityManager instance from an INI resource path. Resources can be acquired from the file system, classpath, or URLs when prefixed with `file:`, `classpath:`, or `url:` respectively. This example uses a `Factory` to ingest a `shiro.ini` file from the root of the classpath and return the `SecurityManager` instance:
``` java
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);
```
<a name="Configuration-SecurityManagerfromanINIinstance"></a>
#[[####SecurityManager from an INI instance]]#
The INI configuration can be constructed programmatically as well if desired via the [`org.apache.shiro.config.Ini`](static/current/apidocs/org/apache/shiro/config/Ini.html) class. The Ini class functions similarly to the JDK [`java.util.Properties`](http://download.oracle.com/javase/6/docs/api/java/util/Properties.html) class, but additionally supports segmentation by section name.
For example:
``` java
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);
```
Now that we know how to construct a `SecurityManager` from INI configuration, let's take a look at exactly how to define a Shiro INI configuration.
<a name="Configuration-INISections"></a>
#[[###INI Sections]]#
INI is basically a text configuration consisting of key/value pairs organized by uniquely-named sections. Keys are unique per section only, not over the entire configuration (unlike the JDK [Properties](http://java.sun.com/javase/6/docs/api/java/util/Properties.html)). Each section may be viewed like a single `Properties` definition however.
Commented lines can start with either with an Octothorpe (# - aka the 'hash', 'pound' or 'number' sign) or a Semi-colon (';')
Here is an example of the sections understood by Shiro:
``` ini
# =======================
# 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
```
<a name="Configuration-%5Cmain%5C"></a>
#[[####[main]]]#
The **`[main]`** section is where you configure the application's `SecurityManager` instance and any of its dependencies, such as [Realm](realm.html "Realm")s.
Configuring object instances like the SecurityManager or any of its dependencies sounds like a difficult thing to do with INI, where we can only use name/value pairs. But through a little bit of convention and understanding of object graphs, you'll find that you can do quite a lot. Shiro uses these assumptions to enable a simple yet fairly concise configuration mechanism.
We often like to refer to this approach as "poor man's" Dependency Injection, and although not as powerful as full-blown Spring/Guice/JBoss XML files, you'll find it gets quite a lot done without much complexity. Of course those other configuration mechanism are available as well, but they're not required to use Shiro.
Just to whet your appetite, here is an example of a valid `[main]` configuration. We'll cover it in detail below, but you might find that you understand quite a bit of what is going on already by intuition alone:
``` ini
[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
```
<a name="Configuration-Defininganobject"></a>
#[[#####Defining an object]]#
Consider the following `[main]` section snippet:
``` ini
[main]
myRealm = com.company.shiro.realm.MyRealm
...
```
This line instantiates a new object instance of type `com.company.shiro.realm.MyRealm` and makes that object available under the **myRealm** name for further reference and configuration.
If the object instantiated implements the `org.apache.shiro.util.Nameable` interface, then the the `Nameable.setName` method will be invoked on the object with the name value ( **`myRealm`** in this example).
<a name="Configuration-Settingobjectproperties"></a>
#[[#####Setting object properties]]#
<a name="Configuration-PrimitiveValues"></a>
#[[######Primitive Values]]#
Simple primitive properties can be assigned just by using the equals sign:
``` ini
...
myRealm.connectionTimeout = 30000
myRealm.username = jsmith
...
```
these lines of configuration translate into method calls:
``` ini
...
myRealm.setConnectionTimeout(30000);
myRealm.setUsername("jsmith");
...
```
How is this possible? It assumes that all objects are [Java Beans](https://en.wikipedia.org/wiki/JavaBean)-compatible [POJO](https://en.wikipedia.org/wiki/Plain_Old_Java_Object)s.
Under the covers, Shiro by default uses Apache Commons [BeanUtils](http://commons.apache.org/proper/commons-beanutils/) to do all the heavy lifting when setting these properties. So although INI values are text, BeanUtils knows how to convert the string values to the proper primitive types and then invoke the corresponding JavaBeans setter method.
<a name="Configuration-ReferenceValues"></a>
#[[######Reference Values]]#
What if the value you need to set is not a primitive, but another object? Well, you can use a dollar sign ($) to reference a previously-defined instance. For example:
``` java
...
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
...
myRealm.credentialsMatcher = $sha256Matcher
...
```
This simply locates the object defined by the name **sha256Matcher** and then uses BeanUtils to set that object on the **myRealm** instance (by calling the `myRealm.setCredentialsMatcher(sha256Matcher)` method).
<a name="Configuration-NestedProperties"></a>
#[[######Nested Properties]]#
Using dotted notation on the left side of the INI line's equals sign, you can traverse an object graph to get to the final object/property that you want set. For example, this config line:
``` java
...
securityManager.sessionManager.globalSessionTimeout = 1800000
...
```
Translates (by BeanUtils) into the following logic:
``` java
securityManager.getSessionManager().setGlobalSessionTimeout(1800000);
```
The graph traversal can be as deep as necessary: `object.property1.property2....propertyN.value = blah`
#tip('BeanUtils Property Support', 'Any property assignment operation supported by the BeanUtils.<a class="external-link" href="https://commons.apache.org/proper/commons-beanutils/apidocs/org/apache/commons/beanutils/BeanUtils.html#setProperty-java.lang.Object-java.lang.String-java.lang.Object-">setProperty</a> method will work in Shiro''s [main] section, including set/list/map element assignments. See the <a class="external-link" href="http://commons.apache.org/proper/commons-beanutils/">Apache Commons BeanUtils Website</a> and documentation for more information.')
<a name="Configuration-ByteArrayValues"></a>
#[[######Byte Array Values]]#
Because raw byte arrays can't be specified natively in a text format, we must use a text encoding of the byte array. The values can be specified either as a Base64 encoded string (the default) or as a Hex encoded string. The default is Base64 because Base64 encoding requires less actual text to represent values - it has a larger encoding alphabet, meaning your tokens are shorter (a bit nicer for text config).
``` ini
# 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==
...
```
However, if you prefer to use Hex encoding instead, you must prefix the String token with `0x` ('zero' 'x'):
``` ini
securityManager.rememberMeManager.cipherKey = 0x3707344A4093822299F31D008
```
<a name="Configuration-CollectionProperties"></a>
#[[######Collection Properties]]#
Lists, Sets and Maps can be set like any other property - either directly or as a nested property. For sets and lists, just specify a comma-delimited set of values or object references.
For example, some SessionListeners:
``` ini
sessionListener1 = com.company.my.SessionListenerImplementation
...
sessionListener2 = com.company.my.other.SessionListenerImplementation
...
securityManager.sessionManager.sessionListeners = $sessionListener1, $sessionListener2
```
For Maps, you specify a comma-delimited list of key-value pairs, where each key-value pair is delimited by a colon ':'
``` ini
object1 = com.company.some.Class
object2 = com.company.another.Class
...
anObject = some.class.with.a.Map.property
anObject.mapProperty = key1:$object1, key2:$object2
```
In the above example, the object referenced by `$object1` will be in the map under the String key `key1`, i.e. `map.get("key1")` returns `object1`. You can also use other objects as the keys:
``` ini
anObject.map = $objectKey1:$objectValue1, $objectKey2:$objectValue2
...
```
<a name="Configuration-Considerations"></a>
#[[#####Considerations]]#
<a name="Configuration-OrderMatters"></a>
#[[######Order Matters]]#
The INI format and conventions above are very convenient and easy to understand, but it is not as powerful as other text/XML-based configuration mechanisms. The most important thing to understand when using the above mechanism is that **Order Matters!**
#warning('Be Careful', 'Each object instantiation and each value assignment is executed <em>in the order they occur in the [main] section</em>. These lines ultimately translate to a JavaBeans getter/setter method invocation, and so those methods are invoked in the same order!
<p>Keep this in mind when writing your configuration.</p>')
<a name="Configuration-OverridingInstances"></a>
#[[######Overriding Instances]]#
Any object can be overridden by a new instance defined later in the configuration. So for example, the 2nd `myRealm` definition would overwrite the first:
``` ini
...
myRealm = com.company.security.MyRealm
...
myRealm = com.company.security.DatabaseRealm
...
```
This would result in `myRealm` being a `com.company.security.DatabaseRealm` instance and the previous instance will never be used (and garbage collected).
<a name="Configuration-DefaultSecurityManager"></a>
#[[######Default SecurityManager]]#
You may have noticed in the complete example above that the SecurityManager instance's class isn't defined, and we jumped right in to just setting a nested property:
``` ini
myRealm = ...
securityManager.sessionManager.globalSessionTimeout = 1800000
...
```
This is because the `securityManager` instance is a special one - it is already instantiated for you and ready to go so you don't need to know the specific `SecurityManager` implementation class to instantiate.
Of course, if you actually _want_ to specify your own implementation, you can, just define your implementation as specified in the "Overriding Instances" section above:
``` ini
...
securityManager = com.company.security.shiro.MyCustomSecurityManager
...
```
Of course, this is rarely needed - Shiro's SecurityManager implementations are very customizable and can typically be configured with anything necessary. You might want to ask yourself (or the user list) if you really need to do this.
[users](#Configuration-users)
<a name="Configuration-%5Cusers%5C"></a>
#[[####[users]]]#
The **`[users]`** section allows you to define a static set of user accounts. This is mostly useful in environments with a very small number of user accounts or where user accounts don't need to be created dynamically at runtime. Here's an example:
``` ini
[users]
admin = secret
lonestarr = vespa, goodguy, schwartz
darkhelmet = ludicrousspeed, badguy, schwartz
```
#info('Automatic IniRealm', 'Just defining non-empty [users] or [roles] sections will automatically trigger the creation of an <a class="external-link" href="static/current/apidocs/org/apache/shiro/realm/text/IniRealm.html"><code>org.apache.shiro.realm.text.IniRealm</code></a> instance and make it available in the [main] section under the name <b><code>iniRealm</code></b>. You can configure it like any other object as described above.')
<a name="Configuration-LineFormat"></a>
#[[#####Line Format]]#
Each line in the [users] section must conform to the following format:
`username` = `password`, _roleName1_, _roleName2_, ..., _roleNameN_
* The value on the left of the equals sign is the username
* The first value on the right of the equals sign is the user's password. A password is required.
* Any comma-delimited values after the password are the names of roles assigned to that user. Role names are optional.
<a name="Configuration-EncryptingPasswords"></a>
#[[#####Encrypting Passwords]]#
If you don't want the [users] section passwords to be in plain-text, you can encrypt them using your favorite hash algorithm (MD5, Sha1, Sha256, etc) however you like and use the resulting string as the password value. By default, the password string is expected to be Hex encoded, but can be configured to be Base64 encoded instead (see below).
#tip('Easy Secure Passwords', 'To save time and use best-practices, you might want to use Shiro''s <a href="command-line-hasher.html" title="Command Line Hasher">Command Line Hasher</a>, which will hash passwords as well as any other type of resource. It is especially convenient for encrypting INI <code>[users]</code> passwords.')
Once you've specified the hashed text password values, you have to tell Shiro that these are encrypted. You do that by configuring the implicitly created `iniRealm` in the [main] section to use an appropriate `CredentialsMatcher` implementation corresponding to the hash algorithm you've specified:
``` ini
[main]
...
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
...
iniRealm.credentialsMatcher = $sha256Matcher
...
[users]
# user1 = sha256-hashed-hex-encoded password, role1, role2, ...
user1 = 2bb80d537b1da3e38bd30361aa855686bde0eacd7162fef6a25fe97bf527a25b, role1, role2, ...
```
You can configure any properties on the `CredentialsMatcher` like any other object to reflect your hashing strategy, for example, to specify if salting is used or how many hash iterations to execute. See the [`org.apache.shiro.authc.credential.HashedCredentialsMatcher`](static/current/apidocs/org/apache/shiro/authc/credential/HashedCredentialsMatcher.html) JavaDoc to better understand hashing strategies and if they might be useful to you.
For example, if your users' password strings were Base64 encoded instead of the default Hex, you could specify:
``` ini
[main]
...
# true = hex, false = base64:
sha256Matcher.storedCredentialsHexEncoded = false
```
<a name="Configuration-%5Croles%5C"></a>
#[[####[roles]]]#
The `**[roles]**` section allows you to associate [Permissions](permissions.html "Permissions") with the roles defined in the [users] section. Again, this is useful in environments with a small number of roles or where roles don't need to be created dynamically at runtime. Here's an example:
``` ini
[roles]
# 'admin' role has all permissions, indicated by the wildcard '*'
admin = *
# The 'schwartz' role can do anything (*) with any lightsaber:
schwartz = lightsaber:*
# The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
# license plate 'eagle5' (instance specific id)
goodguy = winnebago:drive:eagle5
```
<a name="Configuration-LineFormat"></a>
#[[#####Line Format]]#
Each line in the [roles] section must must define a role-to-permission(s) key/value mapping with in the following format:
`rolename` = _permissionDefinition1_, _permissionDefinition2_, ..., _permissionDefinitionN_
where _permissionDefinition_ is an arbitrary String, but most people will want to use strings that conform
to the [`org.apache.shiro.authz.permission.WildcardPermission`](static/current/apidocs/org/apache/shiro/authz/permission/WildcardPermission.html) format for ease of use and flexibility. See the [Permissions](permissions.html "Permissions") documentation for more information on Permissions and how you can benefit from them.
#info('Internal commas', 'Note that if an individual <em>permissionDefinition</em> needs to be internally comma-delimited (e.g. <code>printer:5thFloor:print,info</code>), you will need to surround that definition with double quotes (") to avoid parsing errors:<code>"printer:5thFloor:print,info"</code>')
#tip('Roles without Permissions', 'If you have roles that don''t require permission associations, you don''t need to list them in the [roles] section if you don''t want to. Just defining the role names in the [users] section is enough to create the role if it does not exist yet.')
<a name="Configuration-%5Curls%5C"></a>
#[[####[urls]]]#
This section and its options is described in the [Web](web.html "Web") chapter.
#lendAHandDoc()
<input type="hidden" id="ghEditPage" value="configuration.md.vtl"></input>