001
014
015 package com.liferay.portal.security.auth;
016
017 import com.liferay.portal.kernel.exception.PortalException;
018 import com.liferay.portal.kernel.log.Log;
019 import com.liferay.portal.kernel.log.LogFactoryUtil;
020 import com.liferay.portal.kernel.security.auth.verifier.AuthVerifier;
021 import com.liferay.portal.kernel.security.auth.verifier.AuthVerifierConfiguration;
022 import com.liferay.portal.kernel.security.auth.verifier.AuthVerifierResult;
023 import com.liferay.portal.kernel.util.PropsKeys;
024 import com.liferay.portal.kernel.util.StringPool;
025 import com.liferay.portal.kernel.util.StringUtil;
026 import com.liferay.portal.service.UserLocalServiceUtil;
027 import com.liferay.portal.util.PortalUtil;
028 import com.liferay.registry.Filter;
029 import com.liferay.registry.Registry;
030 import com.liferay.registry.RegistryUtil;
031 import com.liferay.registry.ServiceReference;
032 import com.liferay.registry.ServiceTracker;
033 import com.liferay.registry.ServiceTrackerCustomizer;
034
035 import java.util.ArrayList;
036 import java.util.HashMap;
037 import java.util.Iterator;
038 import java.util.List;
039 import java.util.Map;
040 import java.util.Properties;
041 import java.util.Set;
042 import java.util.concurrent.CopyOnWriteArrayList;
043
044 import javax.servlet.http.HttpServletRequest;
045
046 import jodd.util.Wildcard;
047
048
052 public class AuthVerifierPipeline {
053
054 public static final String AUTH_TYPE = "auth.type";
055
056 public static String getAuthVerifierPropertyName(String className) {
057 String simpleClassName = StringUtil.extractLast(
058 className, StringPool.PERIOD);
059
060 return PropsKeys.AUTH_VERIFIER.concat(simpleClassName).concat(
061 StringPool.PERIOD);
062 }
063
064 public static AuthVerifierResult verifyRequest(
065 AccessControlContext accessControlContext)
066 throws PortalException {
067
068 return _instance._verifyRequest(accessControlContext);
069 }
070
071 private AuthVerifierPipeline() {
072 Registry registry = RegistryUtil.getRegistry();
073
074 Filter filter = registry.getFilter(
075 "(objectClass=" + AuthVerifier.class.getName() + ")");
076
077 _serviceTracker = registry.trackServices(
078 filter, new AuthVerifierTrackerCustomizer());
079
080 _serviceTracker.open();
081 }
082
083 private AuthVerifierResult _createGuestVerificationResult(
084 AccessControlContext accessControlContext)
085 throws PortalException {
086
087 AuthVerifierResult authVerifierResult = new AuthVerifierResult();
088
089 authVerifierResult.setState(AuthVerifierResult.State.SUCCESS);
090
091 HttpServletRequest request = accessControlContext.getRequest();
092
093 long companyId = PortalUtil.getCompanyId(request);
094
095 long defaultUserId = UserLocalServiceUtil.getDefaultUserId(companyId);
096
097 authVerifierResult.setUserId(defaultUserId);
098
099 return authVerifierResult;
100 }
101
102 private List<AuthVerifierConfiguration> _getAuthVerifierConfigurations(
103 AccessControlContext accessControlContext) {
104
105 HttpServletRequest request = accessControlContext.getRequest();
106
107 List<AuthVerifierConfiguration> authVerifierConfigurations =
108 new ArrayList<>();
109
110 String requestURI = request.getRequestURI();
111
112 String contextPath = request.getContextPath();
113
114 requestURI = requestURI.substring(contextPath.length());
115
116 for (AuthVerifierConfiguration authVerifierConfiguration :
117 _authVerifierConfigurations) {
118
119 authVerifierConfiguration = _mergeAuthVerifierConfiguration(
120 authVerifierConfiguration, accessControlContext);
121
122 if (_isMatchingRequestURI(authVerifierConfiguration, requestURI)) {
123 authVerifierConfigurations.add(authVerifierConfiguration);
124 }
125 }
126
127 return authVerifierConfigurations;
128 }
129
130 private boolean _isMatchingRequestURI(
131 AuthVerifierConfiguration authVerifierConfiguration,
132 String requestURI) {
133
134 Properties properties = authVerifierConfiguration.getProperties();
135
136 String[] urlsExcludes = StringUtil.split(
137 properties.getProperty("urls.excludes"));
138
139 if ((urlsExcludes.length > 0) &&
140 (Wildcard.matchOne(requestURI, urlsExcludes) > -1)) {
141
142 return false;
143 }
144
145 String[] urlsIncludes = StringUtil.split(
146 properties.getProperty("urls.includes"));
147
148 if (urlsIncludes.length == 0) {
149 return false;
150 }
151
152 return Wildcard.matchOne(requestURI, urlsIncludes) > -1;
153 }
154
155 private AuthVerifierConfiguration _mergeAuthVerifierConfiguration(
156 AuthVerifierConfiguration authVerifierConfiguration,
157 AccessControlContext accessControlContext) {
158
159 Map<String, Object> settings = accessControlContext.getSettings();
160
161 String authVerifierSettingsKey = getAuthVerifierPropertyName(
162 authVerifierConfiguration.getAuthVerifierClassName());
163
164 boolean merge = false;
165
166 Set<String> settingsKeys = settings.keySet();
167
168 Iterator<String> iterator = settingsKeys.iterator();
169
170 while (iterator.hasNext() && !merge) {
171 String settingsKey = iterator.next();
172
173 if (settingsKey.startsWith(authVerifierSettingsKey)) {
174 if (settings.get(settingsKey) instanceof String) {
175 merge = true;
176 }
177 }
178 }
179
180 if (!merge) {
181 return authVerifierConfiguration;
182 }
183
184 AuthVerifierConfiguration mergedAuthVerifierConfiguration =
185 new AuthVerifierConfiguration();
186
187 mergedAuthVerifierConfiguration.setAuthVerifier(
188 authVerifierConfiguration.getAuthVerifier());
189
190 Properties mergedProperties = new Properties(
191 authVerifierConfiguration.getProperties());
192
193 for (String settingsKey : settings.keySet()) {
194 if (settingsKey.startsWith(authVerifierSettingsKey)) {
195 Object settingsValue = settings.get(settingsKey);
196
197 if (settingsValue instanceof String) {
198 String propertiesKey = settingsKey.substring(
199 authVerifierSettingsKey.length());
200
201 mergedProperties.setProperty(
202 propertiesKey, (String)settingsValue);
203 }
204 }
205 }
206
207 mergedAuthVerifierConfiguration.setProperties(mergedProperties);
208
209 return mergedAuthVerifierConfiguration;
210 }
211
212 private Map<String, Object> _mergeSettings(
213 Properties properties, Map<String, Object> settings) {
214
215 Map<String, Object> mergedSettings = new HashMap<>(settings);
216
217 if (properties != null) {
218 for (Map.Entry<Object, Object> entry : properties.entrySet()) {
219 mergedSettings.put((String)entry.getKey(), entry.getValue());
220 }
221 }
222
223 return mergedSettings;
224 }
225
226 private AuthVerifierResult _verifyRequest(
227 AccessControlContext accessControlContext)
228 throws PortalException {
229
230 if (accessControlContext == null) {
231 throw new IllegalArgumentException(
232 "Access control context is null");
233 }
234
235 List<AuthVerifierConfiguration> authVerifierConfigurations =
236 _getAuthVerifierConfigurations(accessControlContext);
237
238 for (AuthVerifierConfiguration authVerifierConfiguration :
239 authVerifierConfigurations) {
240
241 AuthVerifierResult authVerifierResult = null;
242
243 AuthVerifier authVerifier =
244 authVerifierConfiguration.getAuthVerifier();
245
246 Properties properties = authVerifierConfiguration.getProperties();
247
248 try {
249 authVerifierResult = authVerifier.verify(
250 accessControlContext, properties);
251 }
252 catch (Exception e) {
253 if (_log.isDebugEnabled()) {
254 Class<?> authVerifierClass = authVerifier.getClass();
255
256 _log.debug("Skipping " + authVerifierClass.getName(), e);
257 }
258
259 continue;
260 }
261
262 if (authVerifierResult == null) {
263 Class<?> authVerifierClass = authVerifier.getClass();
264
265 _log.error(
266 "Auth verifier " + authVerifierClass.getName() +
267 " did not return an auth verifier result");
268
269 continue;
270 }
271
272 if (authVerifierResult.getState() !=
273 AuthVerifierResult.State.NOT_APPLICABLE) {
274
275 Map<String, Object> settings = _mergeSettings(
276 properties, authVerifierResult.getSettings());
277
278 settings.put(AUTH_TYPE, authVerifier.getAuthType());
279
280 authVerifierResult.setSettings(settings);
281
282 return authVerifierResult;
283 }
284 }
285
286 return _createGuestVerificationResult(accessControlContext);
287 }
288
289 private static final Log _log = LogFactoryUtil.getLog(
290 AuthVerifierPipeline.class);
291
292 private static final AuthVerifierPipeline _instance =
293 new AuthVerifierPipeline();
294
295 private final List<AuthVerifierConfiguration> _authVerifierConfigurations =
296 new CopyOnWriteArrayList<>();
297 private final ServiceTracker<AuthVerifier, AuthVerifierConfiguration>
298 _serviceTracker;
299
300 private class AuthVerifierTrackerCustomizer
301 implements
302 ServiceTrackerCustomizer<AuthVerifier, AuthVerifierConfiguration> {
303
304 @Override
305 public AuthVerifierConfiguration addingService(
306 ServiceReference<AuthVerifier> serviceReference) {
307
308 Registry registry = RegistryUtil.getRegistry();
309
310 AuthVerifier authVerifier = registry.getService(serviceReference);
311
312 if (authVerifier == null) {
313 return null;
314 }
315
316 Class<?> authVerifierClass = authVerifier.getClass();
317
318 AuthVerifierConfiguration authVerifierConfiguration =
319 new AuthVerifierConfiguration();
320
321 authVerifierConfiguration.setAuthVerifier(authVerifier);
322 authVerifierConfiguration.setAuthVerifierClassName(
323 authVerifierClass.getName());
324 authVerifierConfiguration.setProperties(
325 _loadProperties(serviceReference, authVerifierClass.getName()));
326
327 if (!_validate(authVerifierConfiguration)) {
328 return null;
329 }
330
331 _authVerifierConfigurations.add(0, authVerifierConfiguration);
332
333 return authVerifierConfiguration;
334 }
335
336 @Override
337 public void modifiedService(
338 ServiceReference<AuthVerifier> serviceReference,
339 AuthVerifierConfiguration authVerifierConfiguration) {
340
341 AuthVerifierConfiguration newAuthVerifierConfiguration =
342 new AuthVerifierConfiguration();
343
344 newAuthVerifierConfiguration.setAuthVerifier(
345 authVerifierConfiguration.getAuthVerifier());
346 newAuthVerifierConfiguration.setAuthVerifierClassName(
347 authVerifierConfiguration.getAuthVerifierClassName());
348 newAuthVerifierConfiguration.setProperties(
349 _loadProperties(
350 serviceReference,
351 authVerifierConfiguration.getAuthVerifierClassName()));
352
353 if (_authVerifierConfigurations.remove(authVerifierConfiguration)) {
354 if (!_validate(authVerifierConfiguration)) {
355 return;
356 }
357
358 _authVerifierConfigurations.add(
359 0, newAuthVerifierConfiguration);
360 }
361 }
362
363 @Override
364 public void removedService(
365 ServiceReference<AuthVerifier> serviceReference,
366 AuthVerifierConfiguration authVerifierConfiguration) {
367
368 Registry registry = RegistryUtil.getRegistry();
369
370 registry.ungetService(serviceReference);
371
372 _authVerifierConfigurations.remove(authVerifierConfiguration);
373 }
374
375 private Properties _loadProperties(
376 ServiceReference<AuthVerifier> serviceReference,
377 String authVerifierClassName) {
378
379 Properties properties = new Properties();
380
381 String authVerifierPropertyName = getAuthVerifierPropertyName(
382 authVerifierClassName);
383
384 Map<String, Object> serviceReferenceProperties =
385 serviceReference.getProperties();
386
387 for (String key : serviceReferenceProperties.keySet()) {
388 String propertiesKey = key;
389
390 if (key.startsWith(authVerifierPropertyName)) {
391 propertiesKey = key.substring(
392 authVerifierPropertyName.length());
393 }
394
395 Object value = serviceReferenceProperties.get(key);
396
397 properties.setProperty(propertiesKey, String.valueOf(value));
398 }
399
400 return properties;
401 }
402
403 private boolean _validate(
404 AuthVerifierConfiguration authVerifierConfiguration) {
405
406 Properties properties = authVerifierConfiguration.getProperties();
407
408 String[] urlsIncludes = StringUtil.split(
409 properties.getProperty("urls.includes"));
410
411 if (urlsIncludes.length == 0) {
412 if (_log.isWarnEnabled()) {
413 String authVerifierClassName =
414 authVerifierConfiguration.getAuthVerifierClassName();
415
416 _log.warn(
417 "Auth verifier " + authVerifierClassName +
418 " does not have URLs configured");
419 }
420
421 return false;
422 }
423
424 return true;
425 }
426
427 }
428
429 }