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