/************************************************************************* * * ADOBE CONFIDENTIAL * __________________ * * Copyright 2002 - 2007 Adobe Systems Incorporated * All Rights Reserved. * * NOTICE: All information contained herein is, and remains * the property of Adobe Systems Incorporated and its suppliers, * if any. The intellectual and technical concepts contained * herein are proprietary to Adobe Systems Incorporated * and its suppliers and may be covered by U.S. and Foreign Patents, * patents in process, and are protected by trade secret or copyright law. * Dissemination of this information or reproduction of this material * is strictly forbidden unless prior written permission is obtained * from Adobe Systems Incorporated. **************************************************************************/ package flex.messaging.security; import com.ibm.websphere.security.UserRegistry; import com.ibm.websphere.security.WSSecurityException; import com.ibm.websphere.security.auth.WSLoginFailedException; import com.ibm.ws.security.core.ContextManager; import com.ibm.ws.security.core.ContextManagerFactory; import flex.messaging.FlexContext; import flex.messaging.log.Log; import flex.messaging.log.LogCategories; import javax.security.auth.Subject; import javax.servlet.http.HttpServletRequest; import java.security.Principal; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /* * To setup WebSphere 5.1 for authentication testing: * * 1) Install WebSphere 5.1 * 2) Create two files, users.props and groups.props * (examples in resources/security/websphere) and place them in a directory * under your WS install. * 3) Using the Admin webapp: * * Security > Global Security * Check Enabled * Check Enforce Java 2 Security * Set Active User Registry to Custom * Click OK * * Either the admin app will tell you to setup your Custom or you should * go to Security > User Registries > Custom * * Server User ID should be one of your users from your users.props * Server User Password should be the matching password from users.props * Customer Registry Classname by default is com.ibm.websphere.security.FileRegistrySample * Go to Custom Properties * Add a prop "groupsFile" that points to your groups.props: e.g., c:/websphere5.1/AppServer/security/groups.props * Add a prop "usersFile" that points to your users.props: e.g., c:/websphere5.1/AppServer/security/users.props * * Click OK * * 4) Install your Flex EAR. You may need to go into its Session Settings * page and enable session security there? * * 5) In /java/jre/lib/security edit java.policy and add something * like the following: * grant codeBase "file:${was.install.root}/installedApps/MCHOTIN03/Flex2Ear.ear/secure.war/-" { permission java.security.AllPermission; }; * This gives your webapp all the permissions it needs (possible that it could have * been narrowed down further). * * 6) Edit java.security in teh same directory to add the following entries security.provider.1=com.sun.net.ssl.internal.ssl.Provider security.provider.2=sun.security.provider.Sun * Update the entries below it so they're ordered right. * Copy jsse.jar and jcert.jar into java/jre/lib/ext (I think) * This will get the Flex Proxy to start correctly * * Restart your WebSphere, cross your fingers!!! * */ /** * Authenticates against WebSphere but does not store the authenticated * user in the HttpServletRequest for http attempts due to the container * not providing a mechanism for access. * * @author Paul Reilly * @author Matt Chotin */ public class WebSphereLoginCommand extends AppServerLoginCommand { /** {@inheritDoc} */ public Principal doAuthentication(String username, Object credentials) { Principal principal = null; try { String password = extractPassword(credentials); if (password != null) { ContextManager contextManager = ContextManagerFactory.getInstance(); Subject subject = contextManager.login(contextManager.getDefaultRealm(), username, password); if (subject != null) { //setting the caller subject really doesn't apply for long //it appears to be removed later as each call to //ContextManagerFactory.getInstance() //returns a new instance and we cannot get the real context //and assign values that will be re-used. //this also means that the HttpServletRequest will not have the //information that we've assigned, hence we store this contextManager //in the Principal for later use contextManager.setCallerSubject(subject); principal = new WSLCPrincipal(username, contextManager, subject); } } } catch (WSLoginFailedException wsLoginFailedException) { if (Log.isDebug()) { Log.getLogger(LogCategories.SECURITY).debug("WebSphereLoginCommand#doAuthentication() failed: " + wsLoginFailedException.toString(), wsLoginFailedException); } } catch (WSSecurityException wsSecurityException) { if (Log.isDebug()) { Log.getLogger(LogCategories.SECURITY).debug("WebSphereLoginCommand#doAuthentication() failed: " + wsSecurityException.toString(), wsSecurityException); } } if (Log.isDebug() && principal != null) { Log.getLogger(LogCategories.SECURITY).debug("WebSphereLoginCommand#doAuthentication(). Principal: " + principal + ", Principal class: " + principal.getClass().getName() + ", Principal identity: " + System.identityHashCode(principal)); } return principal; } /** {@inheritDoc} */ public boolean doAuthorization(Principal principal, List roles) { //unfortunately we cannot seem to get the user stored //in the context so the request will never have the information //that we've assigned, therefore we have to do this //every time if (principal == null) return false; if (Log.isDebug()) Log.getLogger(LogCategories.SECURITY).debug("WebSphereLoginCommand#doAuthorization(). Principal: " + principal + ", Principal class: " + principal.getClass().getName() + ", Principal identity: " + System.identityHashCode(principal)); if (principal instanceof WSLCPrincipal) // This code path is hit if this login command handled authentication. { ContextManager contextManager = ((WSLCPrincipal)principal).getContextManager(); UserRegistry registry = contextManager.getRegistry(contextManager.getDefaultRealm()); try { List groups = new ArrayList(registry.getGroupsForUser(principal.getName())); groups.retainAll(roles); // if authorization succeeds, set the user's Subject on this invocation context // so that the rest of the Thread is executed in the context of the appropriate Subject if (groups.size() > 0) ContextManagerFactory.getInstance().setCallerSubject(((WSLCPrincipal)principal).getSubject()); return groups.size() > 0; } catch (Exception e) { } } else // This code path is hit if this login command didn't handle authentication. { // The Principal was not null, meaning we have a WAS Principal in the current HttpServletRequest. // Use that for the authorization check. HttpServletRequest request = FlexContext.getHttpRequest(); for (Iterator iter = roles.iterator(); iter.hasNext(); ) { if (request.isUserInRole((String)iter.next())) return true; } } return false; } /** {@inheritDoc} */ public boolean logout(Principal principal) { //as long as credentials are nulled since we can't store //the authenticated user there's nothing to do return true; } private class WSLCPrincipal implements Principal { private String username; private ContextManager contextManager; private Subject subject; public WSLCPrincipal(String username, ContextManager contextManager, Subject subject) { this.username = username; this.contextManager = contextManager; this.subject = subject; } public String getName() { return username; } public ContextManager getContextManager() { return contextManager; } public Subject getSubject() { return subject; } } }