1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.shiro.config;
20
21 import org.apache.shiro.mgt.DefaultSecurityManager;
22 import org.apache.shiro.mgt.RealmSecurityManager;
23 import org.apache.shiro.mgt.SecurityManager;
24 import org.apache.shiro.realm.Realm;
25 import org.apache.shiro.realm.RealmFactory;
26 import org.apache.shiro.realm.text.IniRealm;
27 import org.apache.shiro.util.CollectionUtils;
28 import org.apache.shiro.util.Factory;
29 import org.apache.shiro.util.LifecycleUtils;
30 import org.apache.shiro.util.Nameable;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.Collections;
37 import java.util.LinkedHashMap;
38 import java.util.List;
39 import java.util.Map;
40
41
42
43
44
45
46 public class IniSecurityManagerFactory extends IniFactorySupport<SecurityManager> {
47
48 public static final String MAIN_SECTION_NAME = "main";
49
50 public static final String SECURITY_MANAGER_NAME = "securityManager";
51 public static final String INI_REALM_NAME = "iniRealm";
52
53 private static transient final Logger log = LoggerFactory.getLogger(IniSecurityManagerFactory.class);
54
55 private ReflectionBuilder builder;
56
57
58
59
60
61 public IniSecurityManagerFactory() {
62 }
63
64 public IniSecurityManagerFactory(Ini config) {
65 setIni(config);
66 }
67
68 public IniSecurityManagerFactory(String iniResourcePath) {
69 this(Ini.fromResourcePath(iniResourcePath));
70 }
71
72 public Map<String, ?> getBeans() {
73 return this.builder != null ? Collections.unmodifiableMap(builder.getObjects()) : null;
74 }
75
76 private SecurityManager getSecurityManagerBean() {
77 return builder.getBean(SECURITY_MANAGER_NAME, SecurityManager.class);
78 }
79
80 protected SecurityManager createDefaultInstance() {
81 return new DefaultSecurityManager();
82 }
83
84 protected SecurityManager createInstance(Ini ini) {
85 if (CollectionUtils.isEmpty(ini)) {
86 throw new NullPointerException("Ini argument cannot be null or empty.");
87 }
88 SecurityManager securityManager = createSecurityManager(ini);
89 if (securityManager == null) {
90 String msg = SecurityManager.class + " instance cannot be null.";
91 throw new ConfigurationException(msg);
92 }
93 return securityManager;
94 }
95
96 private SecurityManager createSecurityManager(Ini ini) {
97 Ini.Section mainSection = ini.getSection(MAIN_SECTION_NAME);
98 if (CollectionUtils.isEmpty(mainSection)) {
99
100 mainSection = ini.getSection(Ini.DEFAULT_SECTION_NAME);
101 }
102 return createSecurityManager(ini, mainSection);
103 }
104
105 protected boolean isAutoApplyRealms(SecurityManager securityManager) {
106 boolean autoApply = true;
107 if (securityManager instanceof RealmSecurityManager) {
108
109 RealmSecurityManager realmSecurityManager = (RealmSecurityManager) securityManager;
110 Collection<Realm> realms = realmSecurityManager.getRealms();
111 if (!CollectionUtils.isEmpty(realms)) {
112 log.info("Realms have been explicitly set on the SecurityManager instance - auto-setting of " +
113 "realms will not occur.");
114 autoApply = false;
115 }
116 }
117 return autoApply;
118 }
119
120 @SuppressWarnings({"unchecked"})
121 private SecurityManager createSecurityManager(Ini ini, Ini.Section mainSection) {
122
123 Map<String, ?> defaults = createDefaults(ini, mainSection);
124 Map<String, ?> objects = buildInstances(mainSection, defaults);
125
126 SecurityManager securityManager = getSecurityManagerBean();
127
128 boolean autoApplyRealms = isAutoApplyRealms(securityManager);
129
130 if (autoApplyRealms) {
131
132
133 Collection<Realm> realms = getRealms(objects);
134
135 if (!CollectionUtils.isEmpty(realms)) {
136 applyRealmsToSecurityManager(realms, securityManager);
137 }
138 }
139
140 return securityManager;
141 }
142
143 protected Map<String, ?> createDefaults(Ini ini, Ini.Section mainSection) {
144 Map<String, Object> defaults = new LinkedHashMap<String, Object>();
145
146 SecurityManager securityManager = createDefaultInstance();
147 defaults.put(SECURITY_MANAGER_NAME, securityManager);
148
149 if (shouldImplicitlyCreateRealm(ini)) {
150 Realm realm = createRealm(ini);
151 if (realm != null) {
152 defaults.put(INI_REALM_NAME, realm);
153 }
154 }
155
156 return defaults;
157 }
158
159 private Map<String, ?> buildInstances(Ini.Section section, Map<String, ?> defaults) {
160 this.builder = new ReflectionBuilder(defaults);
161 return this.builder.buildObjects(section);
162 }
163
164 private void addToRealms(Collection<Realm> realms, RealmFactory factory) {
165 LifecycleUtils.init(factory);
166 Collection<Realm> factoryRealms = factory.getRealms();
167
168 if (!CollectionUtils.isEmpty(factoryRealms)) {
169 realms.addAll(factoryRealms);
170 }
171 }
172
173 private Collection<Realm> getRealms(Map<String, ?> instances) {
174
175
176
177 List<Realm> realms = new ArrayList<Realm>();
178
179
180 for (Map.Entry<String, ?> entry : instances.entrySet()) {
181
182 String name = entry.getKey();
183 Object value = entry.getValue();
184
185 if (value instanceof RealmFactory) {
186 addToRealms(realms, (RealmFactory) value);
187 } else if (value instanceof Realm) {
188 Realm realm = (Realm) value;
189
190 String existingName = realm.getName();
191 if (existingName == null || existingName.startsWith(realm.getClass().getName())) {
192 if (realm instanceof Nameable) {
193 ((Nameable) realm).setName(name);
194 log.debug("Applied name '{}' to Nameable realm instance {}", name, realm);
195 } else {
196 log.info("Realm does not implement the {} interface. Configured name will not be applied.",
197 Nameable.class.getName());
198 }
199 }
200 realms.add(realm);
201 }
202 }
203
204 return realms;
205 }
206
207 private void assertRealmSecurityManager(SecurityManager securityManager) {
208 if (securityManager == null) {
209 throw new NullPointerException("securityManager instance cannot be null");
210 }
211 if (!(securityManager instanceof RealmSecurityManager)) {
212 String msg = "securityManager instance is not a " + RealmSecurityManager.class.getName() +
213 " instance. This is required to access or configure realms on the instance.";
214 throw new ConfigurationException(msg);
215 }
216 }
217
218 protected void applyRealmsToSecurityManager(Collection<Realm> realms, SecurityManager securityManager) {
219 assertRealmSecurityManager(securityManager);
220 ((RealmSecurityManager) securityManager).setRealms(realms);
221 }
222
223
224
225
226
227
228
229
230
231
232
233 protected boolean shouldImplicitlyCreateRealm(Ini ini) {
234 return !CollectionUtils.isEmpty(ini) &&
235 (!CollectionUtils.isEmpty(ini.getSection(IniRealm.ROLES_SECTION_NAME)) ||
236 !CollectionUtils.isEmpty(ini.getSection(IniRealm.USERS_SECTION_NAME)));
237 }
238
239
240
241
242
243
244
245 protected Realm createRealm(Ini ini) {
246
247 IniRealm realm = new IniRealm();
248 realm.setName(INI_REALM_NAME);
249 realm.setIni(ini);
250 return realm;
251 }
252 }