You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ch...@apache.org on 2011/12/24 14:32:59 UTC
svn commit: r1222972 - in /activemq/activemq-apollo/trunk:
apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/
apollo-stomp/src/main/scala/org/apache/activemq/apollo/stomp/
apollo-web/src/main/scala/org/apache/activemq/apollo/web/r...
Author: chirino
Date: Sat Dec 24 13:32:59 2011
New Revision: 1222972
URL: http://svn.apache.org/viewvc?rev=1222972&view=rev
Log:
Fixes APLO-124 : Call the LoginModule.logout method when the user no longer has an active session against the server.
Added:
activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/UserInfo.scala
Modified:
activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/JaasAuthenticator.scala
activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SecurityContext.scala
activemq/activemq-apollo/trunk/apollo-stomp/src/main/scala/org/apache/activemq/apollo/stomp/StompProtocolHandler.scala
activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/BrokerResource.scala
activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/Support.scala
Modified: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/JaasAuthenticator.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/JaasAuthenticator.scala?rev=1222972&r1=1222971&r2=1222972&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/JaasAuthenticator.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/JaasAuthenticator.scala Sat Dec 24 13:32:59 2011
@@ -106,6 +106,7 @@ class JaasAuthenticator(val config: Auth
true
} catch {
case x: Exception =>
+ security_ctx.login_context = null
log.info("authentication failed: local:%s, remote:%s, reason:%s ", security_ctx.local_address, security_ctx.remote_address, x.getMessage)
false
} finally {
Modified: activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SecurityContext.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SecurityContext.scala?rev=1222972&r1=1222971&r2=1222972&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SecurityContext.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-broker/src/main/scala/org/apache/activemq/apollo/broker/security/SecurityContext.scala Sat Dec 24 13:32:59 2011
@@ -17,13 +17,12 @@
package org.apache.activemq.apollo.broker.security
import java.security.Principal
-import collection.mutable.HashSet
import javax.security.auth.Subject
import java.security.cert.X509Certificate
-import org.apache.activemq.apollo.util.OptionSupport._
-import org.apache.activemq.jaas.{GroupPrincipal, UserPrincipal}
-import javax.security.auth.login.LoginContext
import java.net.SocketAddress
+import org.apache.activemq.apollo.broker.Broker.BLOCKABLE_THREAD_POOL
+import org.fusesource.hawtdispatch._
+import javax.security.auth.login.LoginContext
/**
* <p>
@@ -35,6 +34,7 @@ class SecurityContext {
var user:String = _
var password:String = _
+ var sso_token:String = _
var certificates:Array[X509Certificate] = _
var local_address:SocketAddress = _
var remote_address:SocketAddress = _
@@ -91,4 +91,26 @@ class SecurityContext {
}
}
+ /**
+ * Logs the user off, called func when completed. Pass
+ * any errors that occurred during the log off process
+ * to the function or null.
+ */
+ def logout(func: (Throwable)=>Unit) = {
+ if(login_context==null) {
+ func(null)
+ } else {
+ val lc = login_context
+ login_context = null
+ BLOCKABLE_THREAD_POOL {
+ try {
+ lc.logout()
+ func(null)
+ } catch {
+ case e:Throwable => func(e)
+ }
+ }
+ }
+ }
+
}
\ No newline at end of file
Modified: activemq/activemq-apollo/trunk/apollo-stomp/src/main/scala/org/apache/activemq/apollo/stomp/StompProtocolHandler.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-stomp/src/main/scala/org/apache/activemq/apollo/stomp/StompProtocolHandler.scala?rev=1222972&r1=1222971&r2=1222972&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-stomp/src/main/scala/org/apache/activemq/apollo/stomp/StompProtocolHandler.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-stomp/src/main/scala/org/apache/activemq/apollo/stomp/StompProtocolHandler.scala Sat Dec 24 13:32:59 2011
@@ -699,6 +699,11 @@ class StompProtocolHandler extends Proto
host.router.unbind(consumer.destination, consumer, false , security_context)
}
consumers = Map()
+ security_context.logout( e => {
+ if(e!=null) {
+ connection_log.info(e, "STOMP connection '%s' log out error: %s", security_context.remote_address, e.toString)
+ }
+ })
trace("stomp protocol resources released")
}
}
Modified: activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/BrokerResource.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/BrokerResource.scala?rev=1222972&r1=1222971&r2=1222972&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/BrokerResource.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/BrokerResource.scala Sat Dec 24 13:32:59 2011
@@ -36,6 +36,7 @@ import org.apache.activemq.apollo.broker
import java.security.Principal
import org.apache.activemq.apollo.dto._
import javax.ws.rs.core.MediaType._
+import security.SecurityContext
/**
* <p>
@@ -71,37 +72,59 @@ case class BrokerResource() extends Reso
new ArrayList[PrincipalDTO](rc.map(x=>new PrincipalDTO(x.getClass.getName, x.getName)))
}
+ @Produces(Array("text/html;qs=5"))
@GET
@Path("signin")
- def get_signin(@Context response:HttpServletResponse, @QueryParam("username") username:String, @QueryParam("password") password:String):Boolean = {
- post_signin(response, username, password)
+ def get_signin_html(@Context response:HttpServletResponse, @QueryParam("username") username:String, @QueryParam("password") password:String): ErrorDTO = {
+ if(post_signin(response, username, password)) {
+ result(strip_resolve("../.."))
+ } else {
+ var dto = new ErrorDTO()
+ dto.code = "%d: %s".format(BAD_REQUEST.getStatusCode, BAD_REQUEST.getReasonPhrase)
+ dto.message = "Invalid user id or password";
+ result(BAD_REQUEST, dto)
+ }
}
+// @GET
+// @Path("signin")
+// def get_signin(@Context response:HttpServletResponse, @QueryParam("username") username:String, @QueryParam("password") password:String):Boolean = {
+// post_signin(response, username, password)
+// }
+
@POST
@Path("signin")
def post_signin(@Context response:HttpServletResponse, @FormParam("username") username:String, @FormParam("password") password:String):Boolean = {
try {
- http_request.setAttribute("username", username)
- http_request.setAttribute("password", password)
+ val user_info = UserInfo(username, password)
+ http_request.setAttribute("user_info", user_info)
unwrap_future_result[Boolean] {
with_broker { broker =>
monitoring(broker) {
// Only create the session if he is a valid user.
val session = http_request.getSession(true)
- session.setAttribute("username", username)
- session.setAttribute("password", password)
+ user_info.security_context = http_request.getAttribute(SECURITY_CONTEXT_ATTRIBUTE).asInstanceOf[SecurityContext]
+ session.setAttribute("user_info", user_info)
true
}
}
}
} catch {
case e:WebApplicationException => // this happens if user is not authorized
+ e.printStackTrace()
false
}
}
- @GET
- @Path("signout")
+ @Produces(Array("text/html"))
+ @GET @Path("signout")
+ def signout_html():Unit = {
+ signout()
+ result(strip_resolve("../.."))
+ }
+
+ @Produces(Array(APPLICATION_JSON, APPLICATION_XML, TEXT_XML))
+ @GET @Path("signout")
def signout():Unit = {
val session = http_request.getSession(false)
if( session !=null ) {
@@ -480,7 +503,7 @@ case class BrokerResource() extends Reso
Success(rc)
} catch {
case e:Throwable =>
- Failure(create_result(BAD_REQUEST, new ErrorDTO(e.getMessage)))
+ Failure(create_result(BAD_REQUEST, e.getMessage))
}
}
Modified: activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/Support.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/Support.scala?rev=1222972&r1=1222971&r2=1222972&view=diff
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/Support.scala (original)
+++ activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/Support.scala Sat Dec 24 13:32:59 2011
@@ -161,21 +161,37 @@ abstract class Resource(parent:Resource=
protected def authenticate[T](authenticator:Authenticator)(func: (SecurityContext)=>Unit): Unit = {
var security_context = http_request.getAttribute(SECURITY_CONTEXT_ATTRIBUTE).asInstanceOf[SecurityContext]
+ if(security_context == null) {
+ // perhaps we can find it in the session
+ var session = http_request.getSession(false)
+ if( session!=null ) {
+ var user_info = session.getAttribute("user_info").asInstanceOf[UserInfo];
+ if( user_info!=null ) {
+ security_context = user_info.security_context;
+ }
+ }
+ }
+
if( security_context!=null ) {
+ // yay.. user is already logged in.
func(security_context)
} else {
+
security_context = new SecurityContext
security_context.local_address = new InetSocketAddress(http_request.getLocalAddr, http_request.getLocalPort)
security_context.remote_address = new InetSocketAddress(http_request.getRemoteAddr, http_request.getRemotePort)
security_context.certificates = http_request.getAttribute("javax.servlet.request.X509Certificate").asInstanceOf[Array[X509Certificate]]
- if(http_request.getAttribute("username")!=null) {
- security_context.user = http_request.getAttribute("username").asInstanceOf[String];
- security_context.password = http_request.getAttribute("password").asInstanceOf[String];
- } else if( http_request.getSession(false) !=null ) {
+ var user_info = http_request.getAttribute("user_info").asInstanceOf[UserInfo];
+ if( user_info==null ) {
val session = http_request.getSession(false)
- security_context.user = session.getAttribute("username").asInstanceOf[String];
- security_context.password = session.getAttribute("password").asInstanceOf[String];
+ if( session!=null ) {
+ user_info = session.asInstanceOf[UserInfo];
+ }
+ }
+ if(user_info!=null) {
+ security_context.user = user_info.username
+ security_context.password = user_info.password
} else {
var auth_header = http_request.getHeader(HEADER_AUTHORIZATION)
if (auth_header != null && auth_header.length > 0) {
@@ -207,10 +223,23 @@ abstract class Resource(parent:Resource=
}
}
}
+
+ def call_func_with_security = {
+ http_request.setAttribute(SECURITY_CONTEXT_ATTRIBUTE, security_context)
+ try {
+ func(security_context)
+ } finally {
+ // If there is no session, then we have to logout at the end of the request.
+ if( http_request.getSession(false)==null ) {
+ security_context.logout((error)=>{
+ })
+ }
+ }
+ }
+
reset {
if( authenticator.authenticate(security_context) ) {
- http_request.setAttribute(SECURITY_CONTEXT_ATTRIBUTE, security_context)
- func(security_context)
+ call_func_with_security
} else {
func(null)
}
Added: activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/UserInfo.scala
URL: http://svn.apache.org/viewvc/activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/UserInfo.scala?rev=1222972&view=auto
==============================================================================
--- activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/UserInfo.scala (added)
+++ activemq/activemq-apollo/trunk/apollo-web/src/main/scala/org/apache/activemq/apollo/web/resources/UserInfo.scala Sat Dec 24 13:32:59 2011
@@ -0,0 +1,49 @@
+/**
+ * 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 org.apache.activemq.apollo.web.resources
+
+import org.apache.activemq.apollo.broker.security.SecurityContext
+import javax.servlet.http._
+import java.util.concurrent.CountDownLatch
+
+case class UserInfo(username:String, password:String) extends HttpSessionActivationListener with HttpSessionBindingListener {
+
+ //
+ // We hold on to the security_context so we can log the user out of the JAAS login module.
+ // If the session is passivated, expired, or deleted, we automatically log the user
+ // out of the JAAS login module.
+ //
+ @transient
+ var security_context: SecurityContext = null
+
+ def logout = {
+ if(security_context!=null ) {
+ val cd = new CountDownLatch(1)
+ security_context.logout((e)=> {
+ // ignore for now..
+ cd.countDown();
+ })
+ security_context = null
+ cd.await();
+ }
+ }
+
+ def valueBound(event: HttpSessionBindingEvent) {}
+ def valueUnbound(event: HttpSessionBindingEvent) = logout
+ def sessionDidActivate(se: HttpSessionEvent) {}
+ def sessionWillPassivate(se: HttpSessionEvent) = logout
+}