Actually, here is the code.  Attached is the WSS4J callback class and
the CXF interceptor that uses the Acegi authentication manager for
authentication.

Pretty simple and straight forward.  If you look at the callback
handler, you can see my comment regarding the WSS4J engine.  I do have
one concern in that this solution might not have worked for a digest UT.
I'll have to revisit as it has been several months since we first looked
at it.

However, this is a spring board for any discussions. (Spring pun not
intended)

Eric


On Tue, 2007-09-18 at 08:10 -0700, mattmadhavan wrote:
> Eric,
> Do you mind posting a complete example. May be we can have a very
> constructive discussions based on that. 
> 
> Thanks
> Matt
> 
> 
> 
> 
> BigEHokie wrote:
> > 
> > Dan,
> > 
> > What sort of solution are you looking for?  We are using an
> > Acegi/Spring/CXF implementation at our company where we are using
> > WS-Security and Acegi for authentication and AOP/Acegi for
> > authorization.  We could be interested in contributing.
> > 
> > Thanks,
> > Eric
> > 
> > 
> > On Tue, 2007-09-18 at 00:15 +0200, Dan Diephouse wrote:
> >> And I want somebody to contribute a cleaner solution :-D
> >> 
> >> I know there is a lot of stuff we could do with Spring Security/Acegi
> >> that would be super cool. It'd be a real low barrier way to contribute
> >> some stuff if anyone is interested.
> >> 
> >> Cheers,
> >> - Dan
> >> 
> >> mattmadhavan wrote: 
> >> > Hi Ray,
> >> > No I do not want the client side to tell the server! Thats my point.
> >> Some
> >> > good blogs I have seen, do that! Where the client 'tells' which handler
> >> to
> >> > use!
> >> > 
> >> > I want a cleaner ACEGI+ XFIRE solution!
> >> > 
> >> > Thanks
> >> > Matt
> >> > 
> >> > 
> >> > 
> >> > Ray Krueger wrote:
> >> >   
> >> > > You want the client to tell the server how to do security? That
> >> sounds
> >> > > crazy :)
> >> > > 
> >> > > Your client side should either be doing http based security or
> >> > > ws-security. That doesn't have anything to do with Acegi at that
> >> > > point.
> >> > > 
> >> > > On 9/14/07, Zarar Siddiqi <[EMAIL PROTECTED]> wrote:
> >> > >     
> >> > > > I'm trying to understand what you're saying but am having
> >> difficulty. But
> >> > > > here goes:
> >> > > > 
> >> > > >       
> >> > > > > Can some one point me to some docs on the CXF and ACEGI
> >> integration
> >> > > > > or CXF and security like authentication and authorization.
> >> > > > >         
> >> > > > I use Acegi for authorization purposes only. IMHO it doesn't really
> >> make
> >> > > > sense for authentication (WS-Security can do that).  So I use the
> >> > > > MethodSecurityInterceptor and BeanNameAutoProxyCreator to manage
> >> calls to
> >> > > > my
> >> > > > service level methods.  The Acegi docs can help you there, the only
> >> > > > difference I think is that you have to set the authentication token
> >> > > > yourself, e.g.:
> >> > > > 
> >> > > > UsernamePasswordAuthenticationToken token = new
> >> > > > UsernamePasswordAuthenticationToken(
> >> > > >    user.getUsername(), user.getPassword(), user.getAuthorities());
> >> > > > // Populate Acegi Security Context
> >> > > > SecurityContextHolder.getContext().setAuthentication(token);
> >> > > > 
> >> > > >       
> >> > > > > I found some blogs on the CXF+ACEGI, but it is Java centric. On
> >> the
> >> > > > >         
> >> > > > client
> >> > > >       
> >> > > > > side
> >> > > > > we need to set the which class handles the security on the Server
> >> side!
> >> > > > > But if
> >> > > > > I am using some other language for clients like C# it doesn't
> >> seem to
> >> > > > >         
> >> > > > be
> >> > > >       
> >> > > > > the proper way!
> >> > > > >         
> >> > > > You can pass the class name which handles security to the server
> >> (crazy
> >> > > > thought I think!) using a header element and then parse it using
> >> CXF
> >> > > > interceptors.
> >> > > > 
> >> > > > Zarar
> >> > > > 
> >> > > > 
> >> > > > 
> >> > > > 
> >> > > > mattmadhavan wrote:
> >> > > >       
> >> > > > > Any Help will be appreciated!
> >> > > > > 
> >> > > > > 
> >> > > > > 
> >> > > > > mattmadhavan wrote:
> >> > > > >         
> >> > > > > > Hello,
> >> > > > > > Can some one point me to some docs on the CXF and ACEGI
> >> integration or
> >> > > > > > CXF and security like authentication and authorization. Some
> >> sample
> >> > > > > >           
> >> > > > app
> >> > > >       
> >> > > > > > will even be great.
> >> > > > > > 
> >> > > > > > I found some blogs on the CXF+ACEGI, but it is Java centric. On
> >> the
> >> > > > > > client side we need to set the which class handles the security
> >> on the
> >> > > > > > Server side! But if I am using some other language for clients
> >> like C#
> >> > > > > >           
> >> > > > it
> >> > > >       
> >> > > > > > does n't seem to be the proper way!
> >> > > > > > 
> >> > > > > > Any ideas will be greatly appreciated.
> >> > > > > > 
> >> > > > > > Thanks
> >> > > > > > Matt
> >> > > > > > 
> >> > > > > >           
> >> > > > --
> >> > > > View this message in context:
> >> > > > http://www.nabble.com/CXF%2BACEGI-tf4436973.html#a12677582
> >> > > > Sent from the cxf-user mailing list archive at Nabble.com.
> >> > > > 
> >> > > > 
> >> > > >       
> >> > 
> >> >   
> >> 
> >> 
> >> -- 
> >> Dan Diephouse
> >> MuleSource
> >> http://mulesource.com | http://netzooid.com/blog
> > 
> > 
> 
package com.mycompany.security;

import java.util.Vector;

import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationManager;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSUsernameTokenPrincipal;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.handler.WSHandlerResult;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

public class WSAuthenticationInterceptor extends AbstractPhaseInterceptor<SoapMessage> implements
		InitializingBean {
	
	private AuthenticationManager authenticationManager;

	public WSAuthenticationInterceptor() {
		super(Phase.POST_PROTOCOL);
	}

	public void afterPropertiesSet() throws Exception {
		// ensure the 2 objects we need are not null
		Assert.notNull(authenticationManager, "Authentication Manager should not be null!");
	}

	public void handleMessage(SoapMessage message) throws Fault {
		// get out the results from the message context
		Vector<WSHandlerResult> result = (Vector<WSHandlerResult>) message.getContextualProperty(WSHandlerConstants.RECV_RESULTS);
		for (WSHandlerResult res : result) {

			// loop through security engine results
			for (WSSecurityEngineResult secRes : (Vector<WSSecurityEngineResult>) res
					.getResults()) {

				int action = secRes.getAction();

				// determine if the action was a username token
				if ((action & WSConstants.UT) > 0) {

					// get the principal object
					WSUsernameTokenPrincipal principal = (WSUsernameTokenPrincipal) secRes
							.getPrincipal();
					
					Authentication auth = new UsernamePasswordAuthenticationToken(principal.getName(),
							principal.getPassword());
					
					auth = authenticationManager.authenticate(auth);
					
					if(!auth.isAuthenticated()) {
						throw new AuthorizationException("This user is not authentic");
					}
					
					SecurityContextHolder.getContext().setAuthentication(auth);
				}
			}
		}
	}

	/**
	 * @return the authenticationManager
	 */
	public AuthenticationManager getAuthenticationManager() {
		return authenticationManager;
	}

	/**
	 * @param authenticationManager the authenticationManager to set
	 */
	public void setAuthenticationManager(AuthenticationManager authenticationManager) {
		this.authenticationManager = authenticationManager;
	}

}
package com.mycompany.security;

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.log4j.Logger;
import org.apache.ws.security.WSPasswordCallback;

/**
 *
 */
public class WSPasswordCallbackHandler implements CallbackHandler {
	
	private static final Logger logger = Logger.getLogger(WSPasswordCallbackHandler.class);

	/**
	 * 
	 */
	public WSPasswordCallbackHandler() {
	}

	/* (non-Javadoc)
	 * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
	 */
	public void handle(Callback[] callbacks) throws IOException,
			UnsupportedCallbackException {
		try {

			WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];

			if (pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) {

				// because we're not using token digest and we're going to
				// leave security processing up to a custom interceptor,
				// we need to return a blank string to cause WSS4J to
				// continue processing this request rather than return
				// a soap fault due to security reasons
				pc.setPassword("");
			} else {
				throw new UnsupportedCallbackException(pc);
			}
		} catch (UnsupportedCallbackException e) {
			logger.error(
					"handle(Callback[]) - Received unsupported WSPasswordCallback: "
							+ e.getCallback(), e);
			throw e;
		} catch (ArrayIndexOutOfBoundsException e) {
			logger.error(
					"handle(Callback[]) - Received no callbacks in handler", e);
			throw new IllegalArgumentException(e);
		} catch (ClassCastException e) {
			logger
					.error(
							"handle(Callback[]) - Received unexpected Callback in handler",
							e);
			throw new UnsupportedCallbackException(callbacks[0],
					"Unexpected callback");
		}
	}

}

Reply via email to