Actually, I was going to propose to create a new Maven module that contains all Spring Security related code. If we do it like that, then there is no issue with the dependency on Spring Security.
Andreas On Mon, Sep 21, 2009 at 11:40, Sergey Beryozkin <[email protected]> wrote: > Hi > > It is brilliant, thanks. it would be nice to have this feature and a WSS4J > spring security aware password callback handler contributed to CXF but the > issue is we don't actually ship SpringSecurity... > Dan - would it make sense to introduce a 'provided' dependency on the Spring > security (core) modules ? And then modules like ws-security or jaxrs can > have contributions in ....spring.security packages ? > Alternatively we can have this feature and handler demonstrated perhaps in > the system tests area, with the contributions from Andreas being > acknowledged ? > > cheers, Sergey > > ----- Original Message ----- From: "Andreas Veithen" > <[email protected]> > To: <[email protected]> > Sent: Sunday, September 20, 2009 10:16 PM > Subject: Re: CXF + JAX-RS + Spring Security (Acegi) for authorization > > > I improved this a bit further by creating a feature that adds the invoker > proxy: > > public class AuthorizationFeature extends AbstractFeature { > @Override > public void initialize(Server server, Bus bus) { > Service service = server.getEndpoint().getService(); > service.setInvoker(new > SpringSecurityInvokerProxy(service.getInvoker())); > } > } > > Now the configuration looks like this: > > <jaxrs:server address="/rest"> > <jaxrs:serviceBeans> > ... > </jaxrs:serviceBeans> > <jaxrs:providers> > ... > </jaxrs:providers> > <jaxrs:features> > <bean class="myapp.security.AuthorizationFeature"/> > </jaxrs:features> > </jaxrs:server> > > The advantage is that it works in exactly the same way for all > frontends (I tested this successfully with JAX-RS and the simple > frontend) and that there is no need to figure out how to set up the > target invoker. > > Does the code in AuthorizationFeature look good? > > > I also have a working integration between WSS4J and Spring Security > which plays nicely with > SpringSecurityInvokerProxy/AuthorizationFeature. Here is the > configuration for a simple scenario: > > <security:authentication-provider> > <security:user-service> > <security:user name="joe" password="password" > authorities="ROLE_USER,ROLE_ADMIN"/> > <security:user name="bob" password="password" authorities="ROLE_USER"/> > </security:user-service> > </security:authentication-provider> > > <simple:server serviceClass="myapp.MyService" address="/myservice"> > <simple:serviceBean> > <bean class="myapp.MyServiceImpl"/> > </simple:serviceBean> > <simple:inInterceptors> > <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor"> > <constructor-arg> > <map> > <entry key="action" value="UsernameToken"/> > <entry key="passwordType" value="PasswordText"/> > <entry key="passwordCallbackRef"> > <ssec:server-password-callback-handler > logExceptions="true" nestExceptions="false"/> > </entry> > </map> > </constructor-arg> > </bean> > </simple:inInterceptors> > </simple:server> > > ssec:server-password-callback-handler is a Spring handler that creates > a password callback handler that delegates authentication to Spring > Security. > > If there is interest, I can contribute the corresponding code. > > Andreas > > > On Wed, Sep 16, 2009 at 10:54, Sergey Beryozkin > <[email protected]> wrote: >> >> Hi Andreas >> >> This does look like a neat solution. I think it's worth documenting what >> you >> suggested. >> Note that we don't support in-only operations for JAX-RS (just yet), but >> either way, what you've done seems to cover all the variations. In one of >> the system tests I added a custom invoker which extends JAXRSInvoker but >> your approach works well too and is more generic. >> >>> - The service is not necessarily invoked in the same thread as the >>> interceptor >> >> I thought that interceptors and the service were actually invoked on the >> same thread. It is transport threads like Jetty threads won't necessarily >> end up invoking on the service. >> >> Dan, can it be that a thread which invoked a given interceptor won't >> invoke >> the service endpoint ? >> >> By the way there's also a similar test showing how the spring security can >> be used without using annotations : >> >> >> systest/jaxrs/src/test/resources/jaxrs_security_no_annotations/WEB-INF/beans.xml >> >> cheers, Sergey >> >> >> Andreas Veithen-2 wrote: >>> >>> I'm currently trying to integrate JAX-RS with Spring Security for >>> authorization (authorization only; I use a custom authentication >>> mechanism). I found the following resources describing integration >>> between CXF and Spring Security: >>> >>> - >>> >>> http://www.nabble.com/Re:-CXF%2BACEGI-%2B-Anybody-out-there--p12759358.html >>> (WS-Security) >>> - http://www.emforge.org/wiki/WebServicesImplementation (WS-Security) >>> - There is also a JAX-RS systest (see >>> systest/jaxrs/src/test/resources/jaxrs_security/WEB-INF/beans.xml in >>> the trunk) that integrates Spring Security with JAX-RS. >>> >>> In order for (annotation driven) authorization to work, it is >>> necessary to use SecurityContextHolder to associate the >>> SecurityContext/Authentication with the current thread. In the first >>> two references, this is done in a custom interceptor, while the >>> systest uses a servlet filter (that implements HTTP basic >>> authentication). I see two issues with these approaches: >>> - The service is not necessarily invoked in the same thread as the >>> interceptor or servlet filter (e.g. in-only operations). If that >>> happens, the security context will not be set up correctly. >>> - The code in the first two references never resets the authentication >>> in the SecurityContext (by calling >>> SecurityContextHolder.getContext().setAuthentication(null)). I fear >>> that it is therefore possible that a service may accidentally get the >>> authentication from a previous request. This is only a problem when >>> using an interceptor, but using a servlet filter may not always be >>> possible (e.g. for WS-Security). >>> >>> The approach that I use to avoid these problems is to insert a proxy >>> in front of the Invoker (JAXRSInvoker in my case). This proxy looks as >>> follows: >>> >>> public class SpringSecurityInvokerProxy implements Invoker { >>> private Invoker target; >>> >>> public Invoker getTarget() { return target; } >>> public void setTarget(Invoker target) { this.target = target; } >>> >>> public Object invoke(Exchange exchange, Object o) { >>> Authentication authentication = exchange.get(Authentication.class); >>> SecurityContext securityContext = >>> SecurityContextHolder.getContext(); >>> securityContext.setAuthentication(authentication); >>> try { >>> return target.invoke(exchange, o); >>> } finally { >>> securityContext.setAuthentication(null); >>> } >>> } >>> } >>> >>> The Authentication object is added to the exchange by an interceptor >>> that implements the custom authentication mechanism. The try/finally >>> block here makes sure that the security context is reset right after >>> the invocation of the service. The corresponding configuration is: >>> >>> <jaxrs:server address="/rest"> >>> <jaxrs:serviceBeans> >>> ... >>> </jaxrs:serviceBeans> >>> <jaxrs:providers> >>> ... >>> </jaxrs:providers> >>> <jaxrs:invoker> >>> <bean class="myapp.security.SpringSecurityInvokerProxy"> >>> <property name="target"> >>> <bean class="org.apache.cxf.jaxrs.JAXRSInvoker"/> >>> </property> >>> </bean> >>> </jaxrs:invoker> >>> </jaxrs:server> >>> >>> This works well for me, but I would like to know if there is a >>> better/easier way to achieve this. >>> >>> Regards, >>> >>> Andreas >>> >>> >> >> -- >> View this message in context: >> http://www.nabble.com/CXF-%2B-JAX-RS-%2B-Spring-Security-%28Acegi%29-for-authorization-tp25462665p25468445.html >> Sent from the cxf-user mailing list archive at Nabble.com. >> >> > >
