Spring security

HTML translated to java config
see also Java Configuration
see also http://www.springframework.org/schema/security/spring-security.xsd

<http security="none" pattern="/resources/**"/>
<http pattern="/api1/**" create-session="stateless">
	<intercept-url pattern="/**" access="authenticated"/>
	<http-basic />
</http>
<http pattern="/api2/**" create-session="never">
	<intercept-url pattern="/api2/api21/**" access="hasRole('ROLE_ADMIN')"/>
	<intercept-url pattern="/api2/**" access="hasRole('ROLE_USER')"/>
	<http-basic />
</http>
<http pattern="/api3/**">
	<intercept-url pattern="/api3/api31/**" access="hasRole('ROLE_ADMIN')"/>
	<intercept-url pattern="/api3/api32/**" access="hasRole('ROLE_USER')"/>
	<intercept-url pattern="/**" access="authenticated"/>
	<http-basic />
</http>
<http>
	<intercept-url pattern="/logout" access="permitAll"/>
	<intercept-url pattern="/login" access="permitAll"/>
	<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
	...
	<form-login login-page="/services/session" login-processing-url="/login"
				password-parameter="password" username-parameter="username"
				logout-success-url="/services/session" ... />
	<http-basic />
	<logout invalidate-session="true"/>
</http>
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
    @Autowired
    private AuthenticationManager am;

    /**
     * @param auth
     * @throws Exception
     */
    @Autowired
    public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
        auth.parentAuthenticationManager(this.am);
    }
}
@Configuration
@Order(1)
public class Api1Authentication extends WebSecurityConfigurerAdapter {
	@Override
	protected void configure(final HttpSecurity httpSecurity) throws Exception {
		httpSecurity.antMatcher("/api1/**")
					.authorizeRequests().anyRequest().authenticated()
					.and()
					.httpBasic()
					.and()
					.sessionManagement()
					.sessionCreationPolicy(SessionCreationPolicy.STATELESS);    
	}
}
@Configuration
@Order(2)
public class Api2Authentication extends WebSecurityConfigurerAdapter {
	@Override
	protected void configure(final HttpSecurity httpSecurity) throws Exception {
		httpSecurity.antMatcher("/api2/**")
					.authorizeRequests()
					.antMatchers("/api2/api21/**").hasRole("ADMIN")
					.antMatchers("/api2/**").hasRole("USER")
					.and()
					.httpBasic()
					.and()
					.sessionManagement()
					.sessionCreationPolicy(SessionCreationPolicy.NEVER);    
	}
}
@Configuration
@Order(3)
public class Api3Authentication extends WebSecurityConfigurerAdapter {
	@Override
	protected void configure(final HttpSecurity httpSecurity) throws Exception {
		httpSecurity.antMatcher("/api3/**")
					.authorizeRequests()
					.antMatchers("/api3/api31/**").hasRole("ADMIN")
					.antMatchers("/api3/api32/**").hasRole("USER")
					.anyRequest().authenticated()
					.and()
					.httpBasic();    
	}
}
@Configuration
public class OtherAuthentication extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(final WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**");
    }

    @Override
    protected void configure(final HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                    .formLogin()
                    .loginPage("/services/session")
                    .loginProcessingUrl("/login")
                    .usernameParameter("username")
                    .passwordParameter("password")
                    .defaultSuccessUrl("/services/session")
                    .failureHandler(new DdcAuthenticationFailureHandler())
                    .permitAll()
                    .and()
                    .httpBasic()
                    .and()
                    .logout()
                    .logoutSuccessUrl("/services/session")
                    .invalidateHttpSession(true);
    }
}
Q1: why should I use antMatcher("/api2/**") while anyway the subsequent antMatchers(...) cover the entiy /api2/** paths?
A1: because antMatcher has the purpose of mapping the <http/> security configuration while antMatchers accompanies authorizeRequests() in order to specify request access conditions (e.g. roles). antMatchers could accompany also requiresChannel() in order to specify the protocol (http, https, any). If not using antMatcher that would be like <http/> security configuration wouldn't use the pattern attribute (equivalent to using /**).

OtherAuthentication allows the use of form and basic authentication (using the order of declaration). So when not authenticated user access /services/session (using no Authorization header) he would get back a response (e.g. json containing a CSRF token :D). When the user tries to POST /services/session using the received CSRF token he will then be authenticated using basic authentication when he use Authorization header or form authentication otherwise (suppose he uses a valid token otherwise spring will consider a CSRF attack). When one tries to access /some-not-resources-and-not-api123-path with the header Authorization filled with a valid user/password than the basic authentication will be enforced and the user will get the result; if user/password is wrong he will get http code 401. 

/api2/** has SessionCreationPolicy.NEVER which means it won't create a session (when using basic authentication) but it might use one when the user already created one like when authenticated with form-authentication.

/api1/** has SessionCreationPolicy.STATELESS which means it will not create a session but also it will invalidate it if found so it does not live well with OtherAuthentication which creates (in order to use) a session. This means that after a form authentication the user will be disconnected after trying to access /api1/**.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.