http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/src/weblogic/flex/messaging/security/WeblogicLoginCommand.java ---------------------------------------------------------------------- diff --git a/opt/src/weblogic/flex/messaging/security/WeblogicLoginCommand.java b/opt/src/weblogic/flex/messaging/security/WeblogicLoginCommand.java deleted file mode 100755 index 0f698c8..0000000 --- a/opt/src/weblogic/flex/messaging/security/WeblogicLoginCommand.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * 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 java.security.Principal; -import java.util.Iterator; -import java.util.List; - -import javax.security.auth.Subject; -import javax.security.auth.login.LoginException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import weblogic.security.SimpleCallbackHandler; -import weblogic.security.SubjectUtils; -import weblogic.security.services.Authentication; -import weblogic.servlet.security.ServletAuthentication; -import weblogic.security.Security; -import flex.messaging.FlexContext; - -/** - * Authenticates against WebLogic and if using an HttpServlet will store - * the authenticated user in the request. - */ -public class WeblogicLoginCommand extends AppServerLoginCommand implements PrincipalConverter -{ - /** {@inheritDoc} */ - public Principal doAuthentication(String username, Object credentials) - { - Principal principal = null; - - String password = extractPassword(credentials); - - if (password != null) - { - // Test for the presence of a response here (rather than request) because NIO - // endpoints require the alternate code path and they don't populate the response - // in FlexContext. - HttpServletResponse response = FlexContext.getHttpResponse(); - if (response != null) - { - HttpServletRequest request = FlexContext.getHttpRequest(); - int result = ServletAuthentication.FAILED_AUTHENTICATION; - try - { - result = ServletAuthentication.login(username, password, - request); - } - catch (LoginException e) - { - } - catch (NoSuchMethodError noSuchMethodError) - { - //even though we're not supporting WebLogic 7 anymore... - // Weblogic 7.0.4 didn't have login(), so try weak(). - result = ServletAuthentication.weak(username, password, - request); - } - - if (result != ServletAuthentication.FAILED_AUTHENTICATION) - { - // To authorize against the Groups defined via the WL console, we need - // to have a SubjectPrincipal. Because we do not need a principal to authorize - // against web.xml / weblogic.xml, always save the SubjectPrincipal - principal = getSubjectPrincipal(username, password); - } - } - else // Code path for NIO endpoints. - { - principal = getSubjectPrincipal(username, password); - } - } - - return principal; - } - - /** - * Get a SubjectPrincipal for the current user. - * @return the generated SubjectPrincipal - */ - private Principal getSubjectPrincipal(String username, String password) - { - Principal principal=null; - - SimpleCallbackHandler handler = - new SimpleCallbackHandler(username, password); - try - { - Subject subject = Authentication.login(handler); - principal = new SubjectPrincipal(subject); - } - catch (LoginException e) - { - // let authentication fail if this fails - } - - return principal; - } - - /** - * Authorize a user against the Groups defined in the WL console. - * @param principal - Current user principal - * @param roles - Set of roles that allow a succesfull authorization - * @return true if the authorization were succesfull - */ - private boolean doSubjectGroupAuthorization(Principal principal, List roles) - { - boolean authorized = false; - - Subject subject = null; - if (principal instanceof SubjectPrincipal) - { - subject = ((SubjectPrincipal)principal).getSubject(); - } - else - { - subject = Security.getCurrentSubject(); - } - if (subject == null) - { - return false; - } - Iterator iter = roles.iterator(); - while (iter.hasNext()) - { - String role = (String)iter.next(); - if (SubjectUtils.isUserInGroup(subject, role)) - { - authorized = true; - break; - } - } - - return authorized; - } - - /** {@inheritDoc} */ - public boolean doAuthorization(Principal principal, List roles) - { - if (principal == null) - return false; // Avoid NPEs. - - //NOTE: I believe that both HttpServletRequest.isUserInRole and - //SubjectUtils.isUserInGroup returns if the user is in a Weblogic Group, - //not necessarily the Weblogic role construct - - boolean authorized = false; - - // Test for the presence of a response here (rather than request) because NIO - // endpoints require the alternate code path and they don't populate the response - // in FlexContext. - HttpServletResponse response = FlexContext.getHttpResponse(); - if (response != null) - { - HttpServletRequest request = FlexContext.getHttpRequest(); - - // This will attempt to authorize the user against roles configured - // in web.xml and weblogic.xml. - authorized = doAuthorization(principal, roles, request); - - // We also want to support roles defined via the WL console - // attempt this authorization here - if (!authorized) - { - authorized = doSubjectGroupAuthorization(principal, roles); - } - } - else // Code path for NIO endpoints. - { - authorized = doSubjectGroupAuthorization(principal, roles); - } - - return authorized; - } - - /** {@inheritDoc} */ - public boolean logout(Principal principal) - { - HttpServletResponse response = FlexContext.getHttpResponse(); - if (response != null) - { - // Destroy the Principal maintained by the app server. - HttpServletRequest request = FlexContext.getHttpRequest(); - ServletAuthentication.logout(request); - } - // else, current non-servlet session will be automatically invalidated, destroying any active Principal. - - return true; - } - - private class SubjectPrincipal implements Principal - { - private Subject subject; - - public SubjectPrincipal(Subject subject) - { - this.subject = subject; - } - - public String getName() - { - return SubjectUtils.getUserPrincipal(subject).getName(); - } - - public Subject getSubject() - { - return subject; - } - } - - /** {@inheritDoc} */ - public Principal convertPrincipal(Principal principal) - { - if (principal instanceof SubjectPrincipal) - { - return principal; - } - else - { - // We need to do the converting - Subject subject = Security.getCurrentSubject(); - return new SubjectPrincipal(subject); - } - } -}
http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/src/websphere/flex/management/WebSphereMBeanServerLocator.java ---------------------------------------------------------------------- diff --git a/opt/src/websphere/flex/management/WebSphereMBeanServerLocator.java b/opt/src/websphere/flex/management/WebSphereMBeanServerLocator.java deleted file mode 100755 index 533f258..0000000 --- a/opt/src/websphere/flex/management/WebSphereMBeanServerLocator.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.management; - -import java.lang.reflect.Method; - -import javax.management.MBeanServer; - -import flex.messaging.log.Log; -import flex.messaging.log.LogCategories; -import flex.messaging.util.ClassUtil; - -/** - * Custom MBeanServerLocator for use with WebSphere. - * This class locates a MBean server instance via WebSphere's administration APIs. - */ -public class WebSphereMBeanServerLocator implements MBeanServerLocator -{ - //-------------------------------------------------------------------------- - // - // Private Static Variables - // - //-------------------------------------------------------------------------- - - /** - * Localized error constant. - */ - private static final int FAILED_TO_LOCATE_MBEAN_SERVER = 10427; - - //-------------------------------------------------------------------------- - // - // Private Variables - // - //-------------------------------------------------------------------------- - - /** - * Reference to MBeanServer this locator found. - */ - private MBeanServer server; - - //-------------------------------------------------------------------------- - // - // Public Methods - // - //-------------------------------------------------------------------------- - - /** {@inheritDoc} */ - public synchronized MBeanServer getMBeanServer() - { - if (server == null) - { - Class adminServiceClass = ClassUtil.createClass("com.ibm.websphere.management.AdminServiceFactory"); - try - { - Method getMBeanFactoryMethod = adminServiceClass.getMethod("getMBeanFactory", new Class[0]); - Object mbeanFactory = getMBeanFactoryMethod.invoke(null, new Object[0]); - Method getMBeanServerMethod = mbeanFactory.getClass().getMethod("getMBeanServer", new Class[0]); - server = (MBeanServer)getMBeanServerMethod.invoke(mbeanFactory, new Object[0]); - } - catch (Exception e) - { - ManagementException me = new ManagementException(); - me.setMessage(FAILED_TO_LOCATE_MBEAN_SERVER, new Object[] {getClass().getName()}); - me.setRootCause(e); - throw me; - } - if (Log.isDebug()) - Log.getLogger(LogCategories.MANAGEMENT_MBEANSERVER).debug("Using MBeanServer: " + server); - } - return server; - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/src/websphere/flex/messaging/security/WebSphereLoginCommand.java ---------------------------------------------------------------------- diff --git a/opt/src/websphere/flex/messaging/security/WebSphereLoginCommand.java b/opt/src/websphere/flex/messaging/security/WebSphereLoginCommand.java deleted file mode 100755 index cf02d26..0000000 --- a/opt/src/websphere/flex/messaging/security/WebSphereLoginCommand.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * 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; - - } - } -} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/src/websphere/flex/messaging/util/concurrent/AsynchBeansWorkManagerExecutor.java ---------------------------------------------------------------------- diff --git a/opt/src/websphere/flex/messaging/util/concurrent/AsynchBeansWorkManagerExecutor.java b/opt/src/websphere/flex/messaging/util/concurrent/AsynchBeansWorkManagerExecutor.java deleted file mode 100755 index a35c0e9..0000000 --- a/opt/src/websphere/flex/messaging/util/concurrent/AsynchBeansWorkManagerExecutor.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * 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.util.concurrent; - -import javax.naming.InitialContext; -import javax.naming.NamingException; - -import com.ibm.websphere.asynchbeans.Work; -import com.ibm.websphere.asynchbeans.WorkEvent; -import com.ibm.websphere.asynchbeans.WorkException; -import com.ibm.websphere.asynchbeans.WorkListener; -import com.ibm.websphere.asynchbeans.WorkManager; - -import flex.messaging.config.ConfigurationException; -import flex.messaging.log.Log; -import flex.messaging.log.LogCategories; - -/** - * Implements {@link Executor} by delegating command execution to a WAS asynchbeans <code>WorkManager</code>. - * For more information on the asynchbeans API, refer to the WAS Javadoc for - * <a href="http://publib.boulder.ibm.com/infocenter/wasinfo/v5r0/index.jsp?topic=/com.ibm.wasee.doc/info/ee/javadoc/ee/com/ibm/websphere/asynchbeans/WorkManager.html">WorkManager</a>. - * - * - */ -public class AsynchBeansWorkManagerExecutor implements Executor -{ - //-------------------------------------------------------------------------- - // - // Constructor - // - //-------------------------------------------------------------------------- - - /** - * Constructs an <code>AsynchBeansWorkManagerExecutor</code> that will delegate command execution - * to the specified <code>WorkManager</code> instance that is registered in JNDI. - * - * @param workManagerJNDIName The JNDI resource ref name for the <code>WorkManager</code>. - * @see com.ibm.websphere.asynchbeans.WorkManager - */ - public AsynchBeansWorkManagerExecutor(String workManagerJNDIName) - { - try - { - InitialContext ic = new InitialContext(); - workManager = (WorkManager)ic.lookup(workManagerJNDIName); - } - catch(NamingException ne) - { - ConfigurationException ce = new ConfigurationException(); - ce.setMessage(13600, new Object[] {workManagerJNDIName}); - ce.setRootCause(ne); - throw ce; - } - - workListener = new WorkListener() { - public void workAccepted(WorkEvent event) - { - /* No-op */ - } - public void workCompleted(WorkEvent event) - { - // This only needs to be handled if execution of the Runnable failed. - WorkException e = event.getException(); - if (e != null) - { - if (Log.isDebug()) - Log.getLogger(LogCategories.EXECUTOR).error("AsynchBeansWorkManager's WorkListener.workCompleted() callback invoked for failed execution.", e); - - handleFailedExecution(((WorkCommandWrapper)event.getWork()).command, e); - } - } - public void workRejected(WorkEvent event) - { - WorkException e = event.getException(); - if (Log.isDebug()) - Log.getLogger(LogCategories.EXECUTOR).error("AsynchBeansWorkManager's WorkListener.workRejected() callback invoked. WorkException? " + e); - - handleFailedExecution(((WorkCommandWrapper)event.getWork()).command, e); - } - public void workStarted(WorkEvent event) - { - /* No-op */ - } - }; - } - - //-------------------------------------------------------------------------- - // - // Variables - // - //-------------------------------------------------------------------------- - - /** - * Instance level lock for thread-safe state changes. - */ - private final Object lock = new Object(); - - /** - * Reference to the WorkManager instance configured in WAS that this executor instance delegates to. - */ - private final WorkManager workManager; - - /** - * Listener that monitors scheduled work for errors and notifies the FailedExecutionHandler if one has been set. - */ - private final WorkListener workListener; - - //-------------------------------------------------------------------------- - // - // Properties - // - //-------------------------------------------------------------------------- - - //---------------------------------- - // failedExecutionHandler - //---------------------------------- - - private FailedExecutionHandler failedExecutionHandler; - - /** {@inheritDoc} */ - public FailedExecutionHandler getFailedExecutionHandler() - { - synchronized (lock) - { - return failedExecutionHandler; - } - } - - /** {@inheritDoc} */ - public void setFailedExecutionHandler(FailedExecutionHandler value) - { - synchronized (lock) - { - failedExecutionHandler = value; - } - } - - //-------------------------------------------------------------------------- - // - // Public Methods - // - //-------------------------------------------------------------------------- - - /** {@inheritDoc} */ - public void execute(Runnable command) - { - try - { - // Register our listener to monitor each scheduled work, and set the start timeout for the work to indefinite (no queue timeout). - workManager.startWork(new WorkCommandWrapper(command), WorkManager.INDEFINITE, workListener); - } - catch (WorkException e) - { - handleFailedExecution(command, e); - } - } - - //-------------------------------------------------------------------------- - // - // Private Methods - // - //-------------------------------------------------------------------------- - - /** - * Handles command execution problems by notifying the FailedExecutionHandler if one has been set - * and otherwise logging the failure. - * - * @param command The command that failed to execute successfully. - * @param e The exception generated by the failed command. - */ - private void handleFailedExecution(Runnable command, Exception e) - { - FailedExecutionHandler handler = getFailedExecutionHandler(); - if (handler != null) - { - handler.failedExecution(command, this, e); - } - else if (Log.isError()) - { - Log.getLogger(LogCategories.EXECUTOR).error("AsynchBeansWorkManager hit an Exception but no FailedExecutionHandler is registered to handle the error.", e); - } - } - - //-------------------------------------------------------------------------- - // - // Inner Classes - // - //-------------------------------------------------------------------------- - - /** - * Helper class that wraps Runnable commands in the WAS Work interface. - */ - class WorkCommandWrapper implements Work - { - public WorkCommandWrapper(Runnable command) - { - this.command = command; - } - - private final Runnable command; - - public void run() - { - command.run(); - } - - /** - * This is invoked by WAS when the server is shutting down to signal long-running daemon threads spawned by the WorkManager - * to exit from their run() method. Our works are all short lived so this is a no-op; in this case WAS will force any - * works that are executing at server shutdown to terminate. - */ - public void release() - { - // No-op. - } - } -} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/tomcat/pom.xml ---------------------------------------------------------------------- diff --git a/opt/tomcat/pom.xml b/opt/tomcat/pom.xml new file mode 100644 index 0000000..78b33d6 --- /dev/null +++ b/opt/tomcat/pom.xml @@ -0,0 +1,38 @@ +<!-- + +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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.flex.blazeds</groupId> + <artifactId>flex-messaging-opt</artifactId> + <version>4.7.3-SNAPSHOT</version> + </parent> + + <artifactId>flex-messaging-opt-tomcat</artifactId> + <packaging>pom</packaging> + + <modules> + <module>tomcat-base</module> + <module>tomcat-4</module> + <module>tomcat-6</module> + <module>tomcat-7</module> + </modules> + +</project> http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/tomcat/tomcat-4/pom.xml ---------------------------------------------------------------------- diff --git a/opt/tomcat/tomcat-4/pom.xml b/opt/tomcat/tomcat-4/pom.xml new file mode 100644 index 0000000..df46834 --- /dev/null +++ b/opt/tomcat/tomcat-4/pom.xml @@ -0,0 +1,46 @@ +<!-- + +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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.flex.blazeds</groupId> + <artifactId>flex-messaging-opt-tomcat</artifactId> + <version>4.7.3-SNAPSHOT</version> + </parent> + + <artifactId>flex-messaging-opt-tomcat-4</artifactId> + + <dependencies> + <dependency> + <groupId>tomcat</groupId> + <artifactId>catalina</artifactId> + <version>4.0.6</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.flex.blazeds</groupId> + <artifactId>flex-messaging-opt-tomcat-base</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + +</project> http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/tomcat/tomcat-4/src/main/java/flex/messaging/security/TomcatValve4150.java ---------------------------------------------------------------------- diff --git a/opt/tomcat/tomcat-4/src/main/java/flex/messaging/security/TomcatValve4150.java b/opt/tomcat/tomcat-4/src/main/java/flex/messaging/security/TomcatValve4150.java new file mode 100755 index 0000000..182bce4 --- /dev/null +++ b/opt/tomcat/tomcat-4/src/main/java/flex/messaging/security/TomcatValve4150.java @@ -0,0 +1,268 @@ +/* + * 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 flex.messaging.log.Log; +import flex.messaging.log.LogCategories; +import flex.messaging.util.ExceptionUtil; + +import org.apache.catalina.valves.ValveBase; +import org.apache.catalina.Lifecycle; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.LifecycleListener; +import org.apache.catalina.Realm; +import org.apache.catalina.Request; +import org.apache.catalina.Response; +import org.apache.catalina.ValveContext; +import org.apache.catalina.Container; +import org.apache.catalina.Session; +import org.apache.catalina.HttpRequest; +import org.apache.catalina.Manager; +import org.apache.catalina.authenticator.Constants; + +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.io.IOException; +import java.security.Principal; +import java.util.Iterator; +import java.util.List; + +/** + * A Tomcat valve for allowing programmatic login. This valve saves the container, something not available + * normally to a servlet, and allows login to the current realm. The pieces interacting with Tomcat are taken from + * org.apache.catalina.authenticator.AuthenticatorBase. It would be nice if we could just extend that class or + * call some of its methods, but things aren't set up in that class in such a way that this is possible + * + * FIXME: doesn't support Tomcat's SingleSignOn idea. This is a way to write custom valves that associate + * the principal to different web apps or locations. See AuthenticatorBase for details + * + * JAR NOTE: this class is not in flex-messaging.jar but rather flex-tomcat-server.jar + * + * + */ +public class TomcatValve4150 extends ValveBase implements Lifecycle +{ + + private static String AMF_MATCH = "/amfgateway"; + private static String GATEWAY_MATCH = "/flashgateway"; + private static String MESSAGEBROKER_MATCH = "/messagebroker"; + private static String CUSTOM_MATCH = System.getProperty("flex.tomcatValveMatch"); + + public void addLifecycleListener(LifecycleListener listener) + { + // ignore + } + + public LifecycleListener[] findLifecycleListeners() + { + // ignore + return null; + } + + public void removeLifecycleListener(LifecycleListener listener) + { + // ignore + } + + public void start() throws LifecycleException + { + + // RTMP may not go through invoke so we need to put at least one TomcatLoginImpl in the holder. + TomcatLogin login = new TomcatLoginImpl(getContainer(), null); + TomcatLoginHolder.setLogin(login); + // To avoid the thread processes the nio based endpoints does not match the thread start the valve (which is quite possible in Tomcat) + // We set the singleton + TomcatLoginHolder.setNioBasedLogin(login); + } + + public void stop() throws LifecycleException + { + // ignore + } + + public void invoke(Request request, Response response, ValveContext context) + throws IOException, ServletException + { + ServletRequest servRequest = request.getRequest(); + if (servRequest instanceof HttpServletRequest) + { + // we only set the TomcatLoginImpl for gateway paths + + HttpServletRequest hrequest = ((HttpServletRequest)servRequest); + String path = hrequest.getServletPath(); + boolean match = false; + if (path == null) + { + // We need to use a slighly-weaker uri match for 4.1 + String uri = hrequest.getRequestURI(); + match = (uri != null && + (uri.indexOf(MESSAGEBROKER_MATCH) != -1 || + uri.indexOf(AMF_MATCH) != -1 || + uri.indexOf(GATEWAY_MATCH) != -1 || + (CUSTOM_MATCH != null && uri.indexOf(CUSTOM_MATCH) != -1))); + } + else + { + match = (path.startsWith(MESSAGEBROKER_MATCH) || + path.startsWith(AMF_MATCH) || + path.startsWith(GATEWAY_MATCH) || + (CUSTOM_MATCH != null && path.startsWith(CUSTOM_MATCH))); + } + + if (match) + { + HttpRequest httpRequest = (HttpRequest)request; + TomcatLoginHolder.setLogin(new TomcatLoginImpl(getContainer(), httpRequest)); + + // copy over user princicpal and auth type values, just like in AuthenticatorBase.invoke() + Principal principal = hrequest.getUserPrincipal(); + if (principal == null) + { + Session session = getSession(httpRequest, false); + if (session != null) + { + principal = session.getPrincipal(); + if (principal != null) + { + httpRequest.setAuthType(session.getAuthType()); + httpRequest.setUserPrincipal(principal); + } + } + } + } + } + context.invokeNext(request, response); + } + + // from AuthenticatorBase.getSession() + static Session getSession(HttpRequest request, boolean create) + { + + HttpServletRequest hreq = + (HttpServletRequest) request.getRequest(); + + HttpSession hses = hreq.getSession(create); + + if (hses == null) + return (null); + Manager manager = request.getContext().getManager(); + + if (manager == null) + return (null); + else + { + try + { + return (manager.findSession(hses.getId())); + } catch (IOException e) + { + Log.getLogger(LogCategories.SECURITY).error("Error in TomcatValve getting session id " + hses.getId() + " : " + ExceptionUtil.toString(e)); + return (null); + } + } + } + + class TomcatLoginImpl implements TomcatLogin + { + private Container container; + private HttpRequest request; + + TomcatLoginImpl(Container container, HttpRequest request) + { + this.container = container; + this.request = request; + } + + // authenticate the user and associate with the current session. This is taken + // from AuthenticatorBase.register() + public Principal login(String username, String password, HttpServletRequest servletRequest) + { + Realm realm = container.getRealm(); + if (realm == null) + return null; + Principal principal = realm.authenticate(username, password); + + if (principal != null) + { + if (this.request != null && this.request.getRequest() == servletRequest) + { + request.setAuthType("flexmessaging"); //was "flashgateway" + request.setUserPrincipal(principal); + + Session session = getSession(request, true); + + // Cache the authentication information in our session, if any + if (session != null) + { + session.setAuthType("flexmessaging"); //was "flashgateway" + session.setPrincipal(principal); + if (username != null) + session.setNote(Constants.SESS_USERNAME_NOTE, username); + else + session.removeNote(Constants.SESS_USERNAME_NOTE); + if (password != null) + session.setNote(Constants.SESS_PASSWORD_NOTE, password); + else + session.removeNote(Constants.SESS_PASSWORD_NOTE); + } + } + } + + return principal; + } + + public boolean authorize(Principal principal, List roles) + { + + Realm realm = container.getRealm(); + Iterator iter = roles.iterator(); + while (iter.hasNext()) + { + String role = (String)iter.next(); + if (realm.hasRole(principal, role)) + return true; + } + return false; + } + + public boolean logout(HttpServletRequest request) + { + if (this.request != null && this.request.getRequest() == request) + { + Session session = getSession(this.request, false); + if (session != null) + { + session.setPrincipal(null); + session.setAuthType(null); + session.removeNote(Constants.SESS_USERNAME_NOTE); + session.removeNote(Constants.SESS_PASSWORD_NOTE); + } + return true; + } + return false; + } + + /** {@inheritDoc} */ + public Principal convertPrincipal(Principal principal) + { + return principal; + } + } + +} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/tomcat/tomcat-6/pom.xml ---------------------------------------------------------------------- diff --git a/opt/tomcat/tomcat-6/pom.xml b/opt/tomcat/tomcat-6/pom.xml new file mode 100644 index 0000000..c614e6a --- /dev/null +++ b/opt/tomcat/tomcat-6/pom.xml @@ -0,0 +1,50 @@ +<!-- + +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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.flex.blazeds</groupId> + <artifactId>flex-messaging-opt-tomcat</artifactId> + <version>4.7.3-SNAPSHOT</version> + </parent> + + <artifactId>flex-messaging-opt-tomcat-6</artifactId> + + <dependencies> + <dependency> + <groupId>org.apache.tomcat</groupId> + <artifactId>servlet-api</artifactId> + <version>6.0.26</version> + </dependency> + <dependency> + <groupId>org.apache.tomcat</groupId> + <artifactId>catalina</artifactId> + <version>6.0.26</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.flex.blazeds</groupId> + <artifactId>flex-messaging-opt-tomcat-base</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/tomcat/tomcat-6/src/main/java/flex/messaging/security/TomcatValve.java ---------------------------------------------------------------------- diff --git a/opt/tomcat/tomcat-6/src/main/java/flex/messaging/security/TomcatValve.java b/opt/tomcat/tomcat-6/src/main/java/flex/messaging/security/TomcatValve.java new file mode 100755 index 0000000..02a5b31 --- /dev/null +++ b/opt/tomcat/tomcat-6/src/main/java/flex/messaging/security/TomcatValve.java @@ -0,0 +1,275 @@ +/* + * 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 flex.messaging.log.Log; +import flex.messaging.log.LogCategories; +import flex.messaging.util.ExceptionUtil; + +import java.io.IOException; +import java.security.Principal; +import java.util.Iterator; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.catalina.Container; +import org.apache.catalina.Lifecycle; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.LifecycleListener; +import org.apache.catalina.Manager; +import org.apache.catalina.Realm; +import org.apache.catalina.Session; +import org.apache.catalina.Valve; +import org.apache.catalina.authenticator.Constants; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.valves.ValveBase; + +/** + * + * A Tomcat valve for allowing programmatic login. This valve saves the container, + * something not available normally to a servlet, and allows login to the current realm. + * The pieces interacting with Tomcat are taken from org.apache.catalina.authenticator.AuthenticatorBase. + * It would be nice if we could just extend that class or call some of its methods, + * but things aren't set up in that class in such a way that this is possible + * + * FIXME: Doesn't support Tomcat's SingleSignOn which is a way to write custom valves that associate + * the principal to different web apps or locations. See AuthenticatorBase for details + */ +public class TomcatValve extends ValveBase implements Lifecycle +{ + private static final String AUTH_TYPE = "flexmessaging"; // was "flashgateway" + private static final String AMF_MATCH = "/amfgateway"; + private static final String GATEWAY_MATCH = "/flashgateway"; + private static final String MESSAGEBROKER_MATCH = "/messagebroker"; + private static String CUSTOM_MATCH = System.getProperty("flex.tomcatValveMatch"); + + public void invoke(Request request, Response response) throws IOException, ServletException + { + invokeServletRequest(request); + + Valve next = getNext(); + if (next != null) + next.invoke(request, response); + } + + private void invokeServletRequest(Request request) + { + ServletRequest servRequest = request.getRequest(); + if (!(servRequest instanceof HttpServletRequest)) + return; + + // We only set the TomcatLoginImpl for gateway paths + HttpServletRequest hrequest = (HttpServletRequest)servRequest; + boolean match = checkIfPathMatches(hrequest.getServletPath(), hrequest.getRequestURI()); + if (match) + handleMatch(request, hrequest.getUserPrincipal()); + } + + private void handleMatch(Request request, Principal principal) + { + TomcatLoginHolder.setLogin(new TomcatLoginImpl(getContainer(), request)); + + // Copy over user principal and auth type values, just like in AuthenticatorBase.invoke() + if (principal != null) + return; + + Session session = getSession(request, false); + if (session == null) + return; + + principal = session.getPrincipal(); + if (principal != null) + { + request.setAuthType(session.getAuthType()); + request.setUserPrincipal(principal); + } + } + + private boolean checkIfPathMatches(String path, String uri) + { + if (path == null) + { + // We need to use a slighly-weaker uri match for 4.1 + return (uri != null && + (uri.indexOf(MESSAGEBROKER_MATCH) != -1 || + uri.indexOf(AMF_MATCH) != -1 || + uri.indexOf(GATEWAY_MATCH) != -1 || + (CUSTOM_MATCH != null && uri.indexOf(CUSTOM_MATCH) != -1))); + } + else + { + return (path.startsWith(MESSAGEBROKER_MATCH) || + path.startsWith(AMF_MATCH) || + path.startsWith(GATEWAY_MATCH) || + (CUSTOM_MATCH != null && path.startsWith(CUSTOM_MATCH))); + } + } + + public void addLifecycleListener(LifecycleListener listener) + { + // No-op. + } + + public LifecycleListener[] findLifecycleListeners() + { + return null; + } + + public void removeLifecycleListener(LifecycleListener listener) + { + // No-op. + } + + public void start() throws LifecycleException + { + // RTMP may not go through invoke so we need to put at least one TomcatLoginImpl in the holder. + TomcatLogin login = new TomcatLoginImpl(getContainer(), null); + TomcatLoginHolder.setLogin(login); + // To avoid the thread processes the nio based endpoints does not match the thread start the valve (which is quite possible in Tomcat) + // We set the singleton + TomcatLoginHolder.setNioBasedLogin(login); + } + + public void stop() throws LifecycleException + { + // No-op. + } + + // from AuthenticatorBase.getSession() + static Session getSession(Request request, boolean create) + { + + HttpServletRequest hreq = (HttpServletRequest)request.getRequest(); + HttpSession hses = hreq.getSession(create); + + if (hses == null) + return null; + + Manager manager = request.getContext().getManager(); + if (manager == null) + return null; + + try + { + return manager.findSession(hses.getId()); + } + catch (IOException e) + { + Log.getLogger(LogCategories.SECURITY).error("Error in TomcatValve getting session id " + hses.getId() + " : " + ExceptionUtil.toString(e)); + return null; + } + } + + class TomcatLoginImpl implements TomcatLogin + { + private Container container; + private Request request; + + TomcatLoginImpl(Container container, Request request) + { + this.container = container; + this.request = request; + } + + // Authenticate the user and associate with the current session. + // This is taken from AuthenticatorBase.register() + public Principal login(String username, String password, HttpServletRequest servletRequest) + { + Realm realm = container.getRealm(); + if (realm == null) + return null; + + Principal principal = realm.authenticate(username, password); + if (principal == null) + return null; + + if (servletRequestMatches(servletRequest)) + { + request.setAuthType(AUTH_TYPE); + request.setUserPrincipal(principal); + + Session session = getSession(request, true); + + // Cache the authentication information in our session. + if (session != null) + { + session.setAuthType(AUTH_TYPE); + session.setPrincipal(principal); + + if (username != null) + session.setNote(Constants.SESS_USERNAME_NOTE, username); + else + session.removeNote(Constants.SESS_USERNAME_NOTE); + + if (password != null) + session.setNote(Constants.SESS_PASSWORD_NOTE, password); + else + session.removeNote(Constants.SESS_PASSWORD_NOTE); + } + } + + return principal; + } + + public boolean authorize(Principal principal, List roles) + { + Realm realm = container.getRealm(); + Iterator iter = roles.iterator(); + while (iter.hasNext()) + { + String role = (String)iter.next(); + if (realm.hasRole(principal, role)) + return true; + } + return false; + } + + public boolean logout(HttpServletRequest servletRequest) + { + if (servletRequestMatches(servletRequest)) + { + Session session = getSession(request, false); + if (session != null) + { + session.setPrincipal(null); + session.setAuthType(null); + session.removeNote(Constants.SESS_USERNAME_NOTE); + session.removeNote(Constants.SESS_PASSWORD_NOTE); + } + return true; + } + return false; + } + + private boolean servletRequestMatches(HttpServletRequest servletRequest) + { + return request != null && request.getRequest() == servletRequest; + } + + /** {@inheritDoc} */ + public Principal convertPrincipal(Principal principal) + { + return principal; + } + } + +} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/tomcat/tomcat-7/pom.xml ---------------------------------------------------------------------- diff --git a/opt/tomcat/tomcat-7/pom.xml b/opt/tomcat/tomcat-7/pom.xml new file mode 100644 index 0000000..82d0ab8 --- /dev/null +++ b/opt/tomcat/tomcat-7/pom.xml @@ -0,0 +1,45 @@ +<!-- + +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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.flex.blazeds</groupId> + <artifactId>flex-messaging-opt-tomcat</artifactId> + <version>4.7.3-SNAPSHOT</version> + </parent> + + <artifactId>flex-messaging-opt-tomcat-7</artifactId> + + <dependencies> + <dependency> + <groupId>org.apache.tomcat</groupId> + <artifactId>tomcat-catalina</artifactId> + <version>7.0.8</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.flex.blazeds</groupId> + <artifactId>flex-messaging-opt-tomcat-base</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/tomcat/tomcat-7/src/main/java/flex/messaging/security/Tomcat7Valve.java ---------------------------------------------------------------------- diff --git a/opt/tomcat/tomcat-7/src/main/java/flex/messaging/security/Tomcat7Valve.java b/opt/tomcat/tomcat-7/src/main/java/flex/messaging/security/Tomcat7Valve.java new file mode 100755 index 0000000..19eeec8 --- /dev/null +++ b/opt/tomcat/tomcat-7/src/main/java/flex/messaging/security/Tomcat7Valve.java @@ -0,0 +1,313 @@ +/* + * 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 flex.messaging.log.Log; +import flex.messaging.log.LogCategories; +import flex.messaging.util.ExceptionUtil; + +import java.io.IOException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import javax.servlet.ServletConfig; + +import org.apache.catalina.Container; +import org.apache.catalina.Lifecycle; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.LifecycleListener; +import org.apache.catalina.Manager; +import org.apache.catalina.Realm; +import org.apache.catalina.Role; +import org.apache.catalina.Session; +import org.apache.catalina.Valve; +import org.apache.catalina.authenticator.Constants; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.realm.GenericPrincipal; +import org.apache.catalina.users.AbstractUser; +import org.apache.catalina.valves.ValveBase; +import org.apache.catalina .Wrapper; + +/** + * + * A Tomcat valve for allowing programmatic login. This valve saves the container, + * something not available normally to a servlet, and allows login to the current realm. + * The pieces interacting with Tomcat are taken from org.apache.catalina.authenticator.AuthenticatorBase. + * It would be nice if we could just extend that class or call some of its methods, + * but things aren't set up in that class in such a way that this is possible + * + * FIXME: Doesn't support Tomcat's SingleSignOn which is a way to write custom valves that associate + * the principal to different web apps or locations. See AuthenticatorBase for details + */ +public class Tomcat7Valve extends ValveBase implements Lifecycle +{ + private static final String AUTH_TYPE = "flexmessaging"; // was "flashgateway" + private static final String AMF_MATCH = "/amfgateway"; + private static final String GATEWAY_MATCH = "/flashgateway"; + private static final String MESSAGEBROKER_MATCH = "/messagebroker"; + private static String CUSTOM_MATCH = System.getProperty("flex.tomcatValveMatch"); + + public Tomcat7Valve() + { + super(); + + // RTMP may not go through invoke so we need to put at least one TomcatLoginImpl in the holder. + TomcatLogin login = new TomcatLoginImpl(this, null); + TomcatLoginHolder.setLogin(login); + // To avoid the thread processes the nio based endpoints does not match the thread start the valve (which is quite possible in Tomcat) + // We set the singleton + TomcatLoginHolder.setNioBasedLogin(login); + } + + public void invoke(Request request, Response response) throws IOException, ServletException + { + invokeServletRequest(request); + + Valve next = getNext(); + if (next != null) + next.invoke(request, response); + } + + private void invokeServletRequest(Request request) + { + ServletRequest servRequest = request.getRequest(); + if (!(servRequest instanceof HttpServletRequest)) + return; + + // We only set the TomcatLoginImpl for gateway paths + HttpServletRequest hrequest = (HttpServletRequest)servRequest; + boolean match = checkIfPathMatches(hrequest.getServletPath(), hrequest.getRequestURI()); + if (match) + handleMatch(request, hrequest.getUserPrincipal()); + } + + private void handleMatch(Request request, Principal principal) + { + TomcatLoginHolder.setLogin(new TomcatLoginImpl(this, request)); + + // Copy over user principal and auth type values, just like in AuthenticatorBase.invoke() + if (principal != null) + return; + + Session session = getSession(request, false); + if (session == null) + return; + + principal = session.getPrincipal(); + if (principal != null) + { + request.setAuthType(session.getAuthType()); + request.setUserPrincipal(principal); + } + } + + private boolean checkIfPathMatches(String path, String uri) + { + if (path == null) + { + // We need to use a slighly-weaker uri match for 4.1 + return (uri != null && + (uri.indexOf(MESSAGEBROKER_MATCH) != -1 || + uri.indexOf(AMF_MATCH) != -1 || + uri.indexOf(GATEWAY_MATCH) != -1 || + (CUSTOM_MATCH != null && uri.indexOf(CUSTOM_MATCH) != -1))); + } + else + { + return (path.startsWith(MESSAGEBROKER_MATCH) || + path.startsWith(AMF_MATCH) || + path.startsWith(GATEWAY_MATCH) || + (CUSTOM_MATCH != null && path.startsWith(CUSTOM_MATCH))); + } + } + + public void addLifecycleListener(LifecycleListener listener) + { + // No-op. + } + + public LifecycleListener[] findLifecycleListeners() + { + return null; + } + + public void removeLifecycleListener(LifecycleListener listener) + { + // No-op. + } + + // from AuthenticatorBase.getSession() + static Session getSession(Request request, boolean create) + { + + HttpServletRequest hreq = (HttpServletRequest)request.getRequest(); + HttpSession hses = hreq.getSession(create); + + if (hses == null) + return null; + + Manager manager = request.getContext().getManager(); + if (manager == null) + return null; + + try + { + return manager.findSession(hses.getId()); + } + catch (IOException e) + { + Log.getLogger(LogCategories.SECURITY).error("Error in TomcatValve getting session id " + hses.getId() + " : " + ExceptionUtil.toString(e)); + return null; + } + } + + class TomcatLoginImpl implements TomcatLogin + { + private ValveBase valve; + private Request request; + + TomcatLoginImpl(ValveBase valve, Request request) + { + this.valve = valve; + this.request = request; + } + + // Authenticate the user and associate with the current session. + // This is taken from AuthenticatorBase.register() + public Principal login(String username, String password, HttpServletRequest servletRequest) + { + Realm realm = valve.getContainer().getRealm(); + if (realm == null) + return null; + + Principal principal = realm.authenticate(username, password); + if (principal == null) + return null; + + if (servletRequestMatches(servletRequest)) + { + request.setAuthType(AUTH_TYPE); + request.setUserPrincipal(principal); + + Session session = getSession(request, true); + + // Cache the authentication information in our session. + if (session != null) + { + session.setAuthType(AUTH_TYPE); + session.setPrincipal(principal); + + if (username != null) + session.setNote(Constants.SESS_USERNAME_NOTE, username); + else + session.removeNote(Constants.SESS_USERNAME_NOTE); + + if (password != null) + session.setNote(Constants.SESS_PASSWORD_NOTE, password); + else + session.removeNote(Constants.SESS_PASSWORD_NOTE); + } + } + + return principal; + } + + public boolean authorize(Principal principal, List roles) + { + Realm realm = valve.getContainer().getRealm(); + Iterator iter = roles.iterator(); + while (iter.hasNext()) + { + String role = (String)iter.next(); + // For Tomcat 7, we need to get the wrapper from the request to support role mapping in the web.xml. + // This is only supported for servlet endpoints. For NIO endpoints, the wrapper will be null. + Wrapper wrapper = null; + if (request != null) + { + // in the servlet case get the wrapper + wrapper = request.getWrapper(); + } + // for nio the wrapper will be null + if (realm.hasRole(wrapper, principal, role)) + return true; + } + return false; + } + + public boolean logout(HttpServletRequest servletRequest) + { + if (servletRequestMatches(servletRequest)) + { + Session session = getSession(request, false); + if (session != null) + { + session.setPrincipal(null); + session.setAuthType(null); + session.removeNote(Constants.SESS_USERNAME_NOTE); + session.removeNote(Constants.SESS_PASSWORD_NOTE); + } + return true; + } + return false; + } + + private boolean servletRequestMatches(HttpServletRequest servletRequest) + { + return request != null && request.getRequest() == servletRequest; + } + /** {@inheritDoc} */ + public Principal convertPrincipal(Principal principal) + { + if (principal instanceof GenericPrincipal) + { + return principal; + } + else + { + // We need to do the converting + if (principal instanceof AbstractUser) + { + AbstractUser abstractUser = (AbstractUser) principal; + List<String> roles = new ArrayList<String> (); + Iterator roleIterator = abstractUser.getRoles(); + while (roleIterator.hasNext()) + { + Role role = (Role) roleIterator.next(); + roles.add(role.getName()); + } + String userName = abstractUser.getUsername(); + String password = abstractUser.getPassword(); + return new GenericPrincipal(userName, password, roles); + + } + else + { + // no + return principal; + } + } + } + } + +} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/tomcat/tomcat-7/src/main/resources/flex/messaging/security/tomcat-descriptor.xml ---------------------------------------------------------------------- diff --git a/opt/tomcat/tomcat-7/src/main/resources/flex/messaging/security/tomcat-descriptor.xml b/opt/tomcat/tomcat-7/src/main/resources/flex/messaging/security/tomcat-descriptor.xml new file mode 100755 index 0000000..8aef29f --- /dev/null +++ b/opt/tomcat/tomcat-7/src/main/resources/flex/messaging/security/tomcat-descriptor.xml @@ -0,0 +1,67 @@ +<?xml version="1.0"?> +<!-- + + 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. + +--> +<!DOCTYPE mbeans-descriptors PUBLIC + "-//Apache Software Foundation//DTD Model MBeans Configuration File" + "http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd"> + +<!-- + Descriptions of JMX MBeans for Catalina + --> + +<mbeans-descriptors> + + <mbean name="TomcatValve4150" + className="org.apache.catalina.mbeans.ClassNameMBean" + description="Valve that allows Flex to programmatically log in" + domain="Catalina" + group="Valve" + type="flex.messaging.security.TomcatValve4150"> + + <attribute name="className" + description="Fully qualified class name of the managed object" + type="java.lang.String" + writeable="false"/> + + <attribute name="debug" + description="The debugging detail level for this component" + type="int"/> + + + </mbean> + + <mbean name="TomcatValve" + className="org.apache.catalina.mbeans.ClassNameMBean" + description="Valve that allows Flex to programmatically log in" + domain="Catalina" + group="Valve" + type="flex.messaging.security.TomcatValve"> + + <attribute name="className" + description="Fully qualified class name of the managed object" + type="java.lang.String" + writeable="false"/> + + <attribute name="debug" + description="The debugging detail level for this component" + type="int"/> + + + </mbean> +</mbeans-descriptors> http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/tomcat/tomcat-base/pom.xml ---------------------------------------------------------------------- diff --git a/opt/tomcat/tomcat-base/pom.xml b/opt/tomcat/tomcat-base/pom.xml new file mode 100644 index 0000000..96b6337 --- /dev/null +++ b/opt/tomcat/tomcat-base/pom.xml @@ -0,0 +1,30 @@ +<!-- + +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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.flex.blazeds</groupId> + <artifactId>flex-messaging-opt-tomcat</artifactId> + <version>4.7.3-SNAPSHOT</version> + </parent> + + <artifactId>flex-messaging-opt-tomcat-base</artifactId> + +</project> http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/tomcat/tomcat-base/src/main/java/flex/messaging/security/TomcatLogin.java ---------------------------------------------------------------------- diff --git a/opt/tomcat/tomcat-base/src/main/java/flex/messaging/security/TomcatLogin.java b/opt/tomcat/tomcat-base/src/main/java/flex/messaging/security/TomcatLogin.java new file mode 100755 index 0000000..e681461 --- /dev/null +++ b/opt/tomcat/tomcat-base/src/main/java/flex/messaging/security/TomcatLogin.java @@ -0,0 +1,71 @@ +/* + * 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 java.security.Principal; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +/** + * Interface to code in the Tomcat valve. This is needed because Tomcat has a classloader system + * where code in a valve does not appear in the classloader that is used for servlets. + * There is a commons area that both valves and servlets share and this interface + * needs to be placed there. + */ +public interface TomcatLogin +{ + /** + * Attempt to login user with the specified credentials. Return a generated + * Principal object if login were successful + * + * @param username username. + * @param password credentials. + * @param request request via which this login attempt was made + * @return Principal generated for user if login were successful + */ + Principal login(String username, String password, HttpServletRequest request); + + /** + * The gateway calls this method to perform programmatic authorization. + * <p> + * A typical implementation would simply iterate over the supplied roles and + * check that atleast one of the roles returned true from a call to + * HttpServletRequest.isUserInRole(String role). + * </p> + * + * @param principal The principal being checked for authorization + * @param roles A List of role names to check, all members should be strings + * @return true if the principal is authorized given the list of roles + */ + boolean authorize(Principal principal, List roles); + + /** + * Logs out the user associated with the passed-in request. + * + * @param request whose associated user is to be loged-out + * @return true if logout were successful + */ + boolean logout(HttpServletRequest request); + + /** + * Classes that implement the flex.messaging.security.PrinciplaConverter interface, to convert a J2EE Principal to a + * Flex Principal impl. A Flex Principal impl is specific to different Application Servers and will be used by Flex to + * do security authorization check, which calls security framework API specific to Application Servers. + */ + Principal convertPrincipal(Principal principal); +} http://git-wip-us.apache.org/repos/asf/flex-blazeds/blob/fdbf19e4/opt/tomcat/tomcat-base/src/main/java/flex/messaging/security/TomcatLoginCommand.java ---------------------------------------------------------------------- diff --git a/opt/tomcat/tomcat-base/src/main/java/flex/messaging/security/TomcatLoginCommand.java b/opt/tomcat/tomcat-base/src/main/java/flex/messaging/security/TomcatLoginCommand.java new file mode 100755 index 0000000..9624a48 --- /dev/null +++ b/opt/tomcat/tomcat-base/src/main/java/flex/messaging/security/TomcatLoginCommand.java @@ -0,0 +1,124 @@ +/* + * 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 java.security.Principal; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import flex.messaging.FlexContext; +import flex.messaging.util.PropertyStringResourceLoader; + +/** + * A Tomcat specific implementation of LoginCommand. + */ +public class TomcatLoginCommand extends AppServerLoginCommand implements PrincipalConverter +{ + private static final int NO_VALVE = 20000; + + /** {@inheritDoc} */ + public Principal doAuthentication(String username, Object credentials) throws SecurityException + { + TomcatLogin login = TomcatLoginHolder.getLogin(); + if (login == null) + { + SecurityException se = new SecurityException(new PropertyStringResourceLoader(PropertyStringResourceLoader.VENDORS_BUNDLE)); + se.setMessage(NO_VALVE); + throw se; + } + + String password = extractPassword(credentials); + if (password != null) + { + HttpServletRequest request = (HttpServletRequest)FlexContext.getHttpRequest(); + return login.login(username, password, request); + } + + return null; + } + + /** {@inheritDoc} */ + public boolean doAuthorization(Principal principal, List roles) throws SecurityException + { + boolean authorized = false; + + HttpServletRequest request = FlexContext.getHttpRequest(); + // Response is null for NIO endpoints. + HttpServletResponse response = FlexContext.getHttpResponse(); + + if (responseAndRequestNotNull(response, request) + && principalMatchesWithRequest(principal, request)) + { + authorized = doAuthorization(principal, roles, request); + } + else + { + TomcatLogin login = TomcatLoginHolder.getLogin(); + if (login == null) + { + SecurityException se = + new SecurityException(new PropertyStringResourceLoader(PropertyStringResourceLoader.VENDORS_BUNDLE)); + se.setMessage(NO_VALVE); + throw se; + } + authorized = login.authorize(principal, roles); + } + + return authorized; + } + + /** {@inheritDoc} */ + public boolean logout(Principal principal) throws SecurityException + { + HttpServletRequest request = FlexContext.getHttpRequest(); + // Response is null for NIO endpoints. + HttpServletResponse response = FlexContext.getHttpResponse(); + if (responseAndRequestNotNull(response, request)) + { + TomcatLogin login = TomcatLoginHolder.getLogin(); + if (login != null) + { + return login.logout(request); + } + else + { + //TODO should we do this? + //request.getSession(false).invalidate(); + } + } + return true; + } + + private boolean principalMatchesWithRequest(Principal principal, HttpServletRequest request) + { + return principal != null && principal.equals(request.getUserPrincipal()); + } + + private boolean responseAndRequestNotNull(HttpServletResponse response, HttpServletRequest request) + { + return response != null && request != null; + } + + /** {@inheritDoc} */ + public Principal convertPrincipal(Principal principal) + { + TomcatLogin login = TomcatLoginHolder.getLogin(); + return login.convertPrincipal(principal); + } +}
