/** * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright ownership. Apereo * licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use * this file except in compliance with the License. You may obtain a copy of the License at the * following location: * * <p>http://www.apache.org/licenses/LICENSE-2.0 * * <p>Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ package org.apereo.portal.portlet.container.services; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.portlet.PortletRequest; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang.Validate; import org.apache.pluto.container.PortletContainerException; import org.apache.pluto.container.PortletWindow; import org.apache.pluto.container.UserInfoService; import org.apache.pluto.container.om.portlet.PortletApplicationDefinition; import org.apache.pluto.container.om.portlet.UserAttribute; import org.apereo.portal.portlet.om.IPortletDefinition; import org.apereo.portal.portlet.om.IPortletEntity; import org.apereo.portal.portlet.om.IPortletWindow; import org.apereo.portal.portlet.registry.IPortletDefinitionRegistry; import org.apereo.portal.portlet.registry.IPortletEntityRegistry; import org.apereo.portal.portlet.registry.IPortletWindowRegistry; import org.apereo.portal.security.IOpaqueCredentials; import org.apereo.portal.security.IPerson; import org.apereo.portal.security.ISecurityContext; import org.apereo.portal.security.IStringEncryptionService; import org.apereo.portal.security.provider.NotSoOpaqueCredentials; import org.apereo.portal.url.IPortalRequestUtils; import org.apereo.portal.user.IUserInstance; import org.apereo.portal.user.IUserInstanceManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; public class CachedPasswordUserInfoService implements UserInfoService { private IUserInstanceManager userInstanceManager; private IPortletWindowRegistry portletWindowRegistry; private IPortletEntityRegistry portletEntityRegistry; private IPortletDefinitionRegistry portletDefinitionRegistry; private IPortalRequestUtils portalRequestUtils; private IStringEncryptionService stringEncryptionService; protected final Logger log = LoggerFactory.getLogger(getClass()); /** @return the portalRequestUtils */ public IPortalRequestUtils getPortalRequestUtils() { return portalRequestUtils; } /** @param portalRequestUtils the portalRequestUtils to set */ @Autowired(required = true) public void setPortalRequestUtils(IPortalRequestUtils portalRequestUtils) { Validate.notNull(portalRequestUtils); this.portalRequestUtils = portalRequestUtils; } /** The default name of the preferences attribute used to pass the PT to the portlet. */ private String passwordKey = "password"; /** @return the UserInstanceManager */ public IUserInstanceManager getUserInstanceManager() { return userInstanceManager; } /** @param userInstanceManager the UserInstanceManager */ @Autowired(required = true) public void setUserInstanceManager(IUserInstanceManager userInstanceManager) { this.userInstanceManager = userInstanceManager; } /** @return the portletEntityRegistry */ public IPortletEntityRegistry getPortletEntityRegistry() { return this.portletEntityRegistry; } /** @param portletEntityRegistry the portletEntityRegistry to set */ @Autowired(required = true) public void setPortletEntityRegistry(IPortletEntityRegistry portletEntityRegistry) { this.portletEntityRegistry = portletEntityRegistry; } /** @return the portletWindowRegistry */ public IPortletWindowRegistry getPortletWindowRegistry() { return this.portletWindowRegistry; } /** @param portletWindowRegistry the portletWindowRegistry to set */ @Autowired(required = true) public void setPortletWindowRegistry(IPortletWindowRegistry portletWindowRegistry) { this.portletWindowRegistry = portletWindowRegistry; } /** @return the portletDefinitionRegistry */ public IPortletDefinitionRegistry getPortletDefinitionRegistry() { return this.portletDefinitionRegistry; } /** @param portletDefinitionRegistry the portletDefinitionRegistry to set */ @Autowired(required = true) public void setPortletDefinitionRegistry(IPortletDefinitionRegistry portletDefinitionRegistry) { this.portletDefinitionRegistry = portletDefinitionRegistry; } @Autowired public void setStringEncryptionService(IStringEncryptionService stringEncryptionService) { this.stringEncryptionService = stringEncryptionService; } private boolean decryptPassword = false; /** * Set whether the password should be decrypted before adding it to the user info map. * * @param decryptPassword */ public void setDecryptPassword(boolean decryptPassword) { this.decryptPassword = decryptPassword; } /** @return name of the key to save the password under */ public String getPasswordKey() { return passwordKey; } /** @param passwordKey name of the key to save the password under */ public void setPasswordKey(String passwordKey) { this.passwordKey = passwordKey; } /* * (non-Javadoc) * @see org.apache.pluto.container.UserInfoService#getUserInfo(javax.portlet.PortletRequest, org.apache.pluto.container.PortletWindow) */ @Override public Map<String, String> getUserInfo(PortletRequest request, PortletWindow portletWindow) throws PortletContainerException { Map<String, String> userInfo = new HashMap<String, String>(); // check to see if a password is expected by this portlet if (isPasswordRequested(request, portletWindow)) { log.debug( "Portlet named {} wants a password", portletWindow.getPortletDefinition().getPortletName()); final HttpServletRequest httpServletRequest = this.portalRequestUtils.getPortletHttpRequest(request); final IUserInstance userInstance = userInstanceManager.getUserInstance(httpServletRequest); final IPerson person = userInstance.getPerson(); final ISecurityContext context = person.getSecurityContext(); // if it is, attempt to request a password String password = getPassword(context); log.debug(password != null ? "Have a non-null password" : "password was null"); if (this.decryptPassword && password != null) { log.debug("Attempting to decrypt password"); password = stringEncryptionService.decrypt(password); log.debug( "Password decryption complete, password is length {}", password != null ? password.length() : "is null"); } if (password != null) { userInfo.put(this.passwordKey, password); log.debug( "Found password with length {} for portlet name {}", password.length() != 0 ? "non-zero" : 0, portletWindow.getPortletDefinition().getPortletName()); } } return userInfo; } /** * Determine whether the portlet has expects a password as one of the user attributes. * * @param request portlet request * @param plutoPortletWindow portlet window * @return <code>true</code> if a password is expected, <code>false</code> otherwise * @throws PortletContainerException if expeced attributes cannot be determined */ public boolean isPasswordRequested(PortletRequest request, PortletWindow plutoPortletWindow) throws PortletContainerException { // get the list of requested user attributes final HttpServletRequest httpServletRequest = this.portalRequestUtils.getPortletHttpRequest(request); final IPortletWindow portletWindow = this.portletWindowRegistry.convertPortletWindow( httpServletRequest, plutoPortletWindow); final IPortletEntity portletEntity = portletWindow.getPortletEntity(); final IPortletDefinition portletDefinition = portletEntity.getPortletDefinition(); final PortletApplicationDefinition portletApplicationDescriptor = this.portletDefinitionRegistry.getParentPortletApplicationDescriptor( portletDefinition.getPortletDefinitionId()); // check to see if the password key is one of the requested user attributes List<? extends UserAttribute> requestedUserAttributes = portletApplicationDescriptor.getUserAttributes(); for (final UserAttribute userAttributeDD : requestedUserAttributes) { final String attributeName = userAttributeDD.getName(); if (attributeName.equals(this.passwordKey)) return true; } // if the password key wasn't found in the list of requested attributes return false; } /** * Retrieves the users password by iterating over the user's security contexts and returning the * first available cached password. * * @param baseContext The security context to start looking for a password from. * @return the users password */ private String getPassword(ISecurityContext baseContext) { String password = null; IOpaqueCredentials oc = baseContext.getOpaqueCredentials(); if (oc instanceof NotSoOpaqueCredentials) { NotSoOpaqueCredentials nsoc = (NotSoOpaqueCredentials) oc; password = nsoc.getCredentials(); } // If still no password, loop through subcontexts to find cached credentials Enumeration en = baseContext.getSubContexts(); while (password == null && en.hasMoreElements()) { ISecurityContext subContext = (ISecurityContext) en.nextElement(); password = this.getPassword(subContext); } return password; } }