For some time ago I was struggling with GWTP based application, which I had to make work with Spring Security. Usually GWT web applications are one-page projects so that means there is no much Web-part from Spring Security:
Using JavaConfig in your WebSecurityConfigurerAdapter:
@Override
protected void configure(HttpSecurity http) throws Exception {
//Allowing all URLs as the security is only method-based (there is no login page per se)
http.authorizeRequests().antMatchers("/**").permitAll();
http.httpBasic().authenticationEntryPoint(entryPoint());
//It's enabled by default for JavaConfig
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
}
The entryPoint() returns empty AuthenticationEntryPoint (authentication is implemented with GWTP presenter, hence there is no separate LoginForm)Identical using XML:
<beans:bean class="com.jdsu.nse.mac.server.security.ActionAuthenticationEntryPoint" id="entryPoint">
<http entry-point-ref="entryPoint" use-expressions="true">
<intercept-url access="permitAll()" pattern="/**">
</session-management>
</http>
The communication with the server was implemented using Action pattern described on Google I/O (an implemented in GWTP). The trickiest part was to make Spring Security work with Action handlers. GWTP supports Spring as a DI on the server side so Guice had to be replaced with Spring (even though I'd prefer Guice over Spring). The crucial point to make it all work is to tell Spring Security to generate proxies for the classes (each particular ActionHandler implementation) as opposed to interface-based proxy generation.Using JavaConfig annotate WebSecurityConfigurerAdapter with:
@EnableGlobalMethodSecurity(proxyTargetClass = true, securedEnabled = true)Notice proxyTargetClass = true. Without this Spring Security will generate all proxies based on ActionHandler interface and GWTP won't be able to call any specific handler implementation for passed Action type.
The same in XML:
<global-method-security secured-annotations="enabled" proxy-target-class="true" />Finally, to convert Spring Security exceptions to custom client exceptions you need to rewrite three classes from GWTP (basically copy/paste) - DispatchModule, HandlerModule and DispatchImpl.
Change default dispatchClass in your custom DispatchModule to SecureDispatchImpl implementation. Your application HandlerModule then would have to extend your custom HandlerModule. This way you can tell GWTP to use SecureDispatchModule:
public class SecureDispatchImpl extends AbstractDispatchImpl {
@Autowired
public SecureDispatchImpl(ActionHandlerValidatorRegistry actionHandlerValidatorRegistry) {
super(actionHandlerValidatorRegistry);
}
public <A extends Action<R>, R extends Result> R execute(A action)
throws ActionException, ServiceException {
try {
return super.execute(action);
} catch (ServiceException e) {
if (e.getCause() instanceof AccessDeniedException) {
if (SecurityContextHolder.getContext().getAuthentication() instanceof
AnonymousAuthenticationToken) {
throw new AuthenticationException();
} else {
throw new AuthorizationException(e.getCause().getMessage());
}
}
throw e;
}
}
}
For now I didn't find any better solution to override DispatchImpl.P.S.: don't forget to make all your custom role names to have ROLE_ prefix. I've spent several hours before I found why my user with correct role wasn't allowed to call action handler annotated with the same role name (apparently it doesn't work without ROLE_ prefix).