| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF 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 |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * 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 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 <websphere_dir>/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. |
| */ |
| public class WebSphereLoginCommand extends AppServerLoginCommand implements PrincipalConverter { |
| |
| /** |
| * {@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; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public Principal convertPrincipal(Principal principal) { |
| if (principal instanceof WSLCPrincipal) { |
| // We are good |
| return principal; |
| } else { |
| // we need the converting |
| |
| ContextManager contextManager = ContextManagerFactory.getInstance(); |
| |
| Subject subject = null; |
| try { |
| subject = contextManager.getCallerSubject(); |
| } catch (WSSecurityException e) { |
| |
| } |
| |
| if (subject != null) { |
| return new WSLCPrincipal(principal.getName(), contextManager, subject); |
| } else |
| // Just return the old one |
| return principal; |
| |
| } |
| } |
| } |