If we have a consumer facing web interface
typically accessed by web browsers where we need to maintain a user session we
have to end up having a form based authentication mechanism. Third party
clients for B2B service consumption we can have token based security in place
and mobile users security could be supported by OAuth2. Lets see how we could
implement all three types of security mechanisms in a web application using
Spring Security.
Security Configuration files for REST and Form
based security :-
@Configuration
@EnableWebSecurity
public class MultiHttpSecurityConfig
{
@Configuration
@Order(1)
public static class RestSecurityConfig extends WebSecurityConfigurerAdapter
{
@Bean
public RestAuthenticationEntryPoint
restAuthenticationEntryPoint() {
RestAuthenticationEntryPoint entryPoint = new RestAuthenticationEntryPoint();
entryPoint.setRealmName("<your_realm_name>");
return entryPoint;
}
@Bean
public RestAuthenticationProvider restAuthenticationProvider()
{
RestAuthenticationProvider authProvider = new RestAuthenticationProvider();
return authProvider;
}
@Bean
public RestSecurityFilter restSecurityFilter() {
RestSecurityFilter filter = null;
try {
filter = new RestSecurityFilter(authenticationManagerBean());
} catch (Exception e) {
e.printStackTrace();
}
return filter;
}
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.csrf().disable();
http
.antMatcher("/api/**")
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
//.addFilterBefore(restSecurityFilter(),
BasicAuthenticationFilter.class)
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint()).and()
.authorizeRequests()
.antMatchers("/api/**")
.authenticated().and().addFilterBefore(restSecurityFilter(),
BasicAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception
{
authManagerBuilder.authenticationProvider(restAuthenticationProvider());
}
}
@Configuration
public static class FormSecurityConfig extends WebSecurityConfigurerAdapter
{
@Autowired
DataSource dataSource;
@Autowired
private <custom_user_detail_service> customUserDetailsService;
@Autowired
CustomSecuritySuccessHandler customSecuritySuccessHandler;
@Autowired
CustomSecurityFailureHandler customSecurityFailureHandler;
@Autowired
private <password_encoder> passwordEncoder;
@Autowired
private CustomAccessDeniedHandler customAccessDeniedHandler;
@Override
public void configure(WebSecurity web) throws Exception
{
web.ignoring().antMatchers("/resources/**");
}
protected void configure(HttpSecurity http) throws Exception
{
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/", "/login.html", "/app/**", "/assets/**", "/login","/failure","/register","/public/**", "/oauth/v1/**").permitAll().anyRequest().authenticated();
http.formLogin().loginPage("/login").failureUrl("/")
.successHandler(customSecuritySuccessHandler)
.failureHandler(customSecurityFailureHandler).permitAll().and()
.logout().logoutSuccessUrl("/login").permitAll().and()
.rememberMe().and().exceptionHandling().accessDeniedHandler(customAccessDeniedHandler);
return;
}
@Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder)
throws Exception {
authManagerBuilder.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder);
}
}
}
OAuth2
Security Configuartion:-
@Configuration
public class GlobalAuthenticationConfig extends GlobalAuthenticationConfigurerAdapter
{
@Autowired
private <custom_user_detail_service> oAuthUserDetailService;
@Autowired
private <password_encoder> commonPasswordEncoder;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(oAuthUserDetailService).passwordEncoder(commonPasswordEncoder);
}
}
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter
{
@Autowired
DataSource dataSource;
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
{
clients.jdbc(dataSource);
}
@Bean
public TokenStore
tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception
{
endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception
{
oauthServer.allowFormAuthenticationForClients();
}
}
@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter
{
private static final String HU_REST_RESOURCE_ID = "rest_api";
@Autowired
DataSource dataSource;
@Bean
public TokenStore
tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Override
public void configure(ResourceServerSecurityConfigurer resources)
{
resources.resourceId(HU_REST_RESOURCE_ID).stateless(false);
}
@Override
public void configure(HttpSecurity http) throws Exception
{
http.
requestMatchers().antMatchers("/oauth/v1/**").and().
authorizeRequests().antMatchers("/oauth/v1/**").access("#oauth2.hasScope('read')
or (!#oauth2.isOAuth() and hasRole('ROLE_USER'))");
}
}
With
these configurations the incoming requests with URL pattern -
i.
<context>/api/<version>/<some_request> will be
intercepted by RestSecurityConfig
ii.
<context>/oauth/v1/<some_request> will be intercepted by
OAuth2ResourceServerConfig
iii. All
other requests will be intercepted by FormSecurityConfig
This comment has been removed by the author.
ReplyDeleteHi Badal, In your Git hub project I didn't find any implementation for the com.test.security.rest.filter.SubscriptionService interface. I thing it is missing in the project. Could u please check it and commit the impl file.
ReplyDeleteThis comment has been removed by the author.
DeleteHi,
DeleteThx for figuring it out. Added a pseudo method impl sample for your reference.
Thx,
Badal