user2057006
user2057006

Reputation: 647

Spring Security Ant Matchers for home root / - spring boot 1.4.2 release version

I have a requirement to display custom based login form(/auth/login.html) through spring security when user hits http://localhost:8080. If user login successfully with admin role, redirect the user to /admin/adminsuccess.html. Once admin user redirected to /adminsuccess.html, I need to permit admin user to access other pages e.g. (/admin/assetallocate.html,/admin/assetdeallocate.html..)If user not logging in with admin role, show the same login page with errors..

Below are my code:

 @Configuration
    public class AssetWebConfig extends WebMvcConfigurerAdapter {

        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("auth/login");
        registry.addViewController("/admin/adminsuccess").setViewName("admin/auth-success");
        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
    }

    }

    @Configuration
    @EnableWebSecurity
    @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
        .authorizeRequests()
        .antMatchers("/login").permitAll()
        .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')") 
        .antMatchers("/**").access("hasRole('ROLE_ADMIN')")
            .and()
        .formLogin()
            .loginPage("/login")
            .usernameParameter("username")
            .passwordParameter("password")
            .defaultSuccessUrl("/admin/adminsuccess")
            .and()
        .logout()
            .logoutSuccessUrl("/login?logout")
            .permitAll()
            .and()
            .csrf().disable();
}

}

/auth/login.html
    <form name="loginform" th:action="@{/login}" method="post" class="form-signin">

Above code whatever i written not working as expected. It could be the issue with ant matches pattern. Please guide.

Update: When i hit "http://localhost:8080", custom login page is displaying now. But when i enter correct credentials, it's not re-directing to view name '/admin/auth-success.html' based on AssetWebConfig.java configuration. Below is the current response if i enter correct credentials.

This application has no explicit mapping for /error, so you are seeing this as a fallback.
Wed Nov 23 11:42:59 IST 2016
There was an unexpected error (type=Not Found, status=404).
No message available

Upvotes: 1

Views: 10332

Answers (1)

satya-j
satya-j

Reputation: 349

Yes. Issue is with your ant matchers.

As per my understanding, when you say anyRequest.permitAll , it doesn't comply with antMatchers("/admin/*").access("hasRole('ROLE_ADMIN')") because you're telling web security to allow every request to go through without authorization.

Change as below,

http.authorizeRequests()
        .antMatchers("/login").permitAll()
        .antMatchers("/admin/**").access("hasRole('ADMIN')")
        .and().formLogin().loginPage("/login")

https://github.com/satya-j/rab/blob/master/src/main/java/com/satya/rab/config/WebSecurityConfig.java - refer to this, its my repo where I had earlier tried out with spring security.

EDIT:

Here is an update

WebSecurityConfig

.antMatchers("/login").permitAll()
.antMatchers("/admin/**").access("hasRole('ADMIN')")
.antMatchers("/**").access("hasRole('USER')")
.and()
.formLogin().loginPage("/login")
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/index")
.failureUrl("/login?error");

You can use a authentication provider of your choice to set roles based on the user.

CustomeAuthenticationProvider

@Component("authProvider")
public class CustomAuthenticationProvider implements AuthenticationProvider     {

@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
    String username = auth.getName();
    String password = auth.getCredentials().toString();

    if(username.equals("user") && password.equals("user")) {
        List<GrantedAuthority> grantedAuths = new ArrayList<GrantedAuthority>();
        grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
        return new UsernamePasswordAuthenticationToken(username, password, grantedAuths);
    } else if(username.equals("admin") && password.equals("admin")) {
        List<GrantedAuthority> grantedAuths = new ArrayList<GrantedAuthority>();
        grantedAuths.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
        return new UsernamePasswordAuthenticationToken(username, password, grantedAuths);
    } else {
        throw new CustomException("Unable to auth against third party systems");
    }
}

@Override
public boolean supports(Class<?> auth) {
    return auth.equals(UsernamePasswordAuthenticationToken.class);
}

I've used a Custom authentication. As I'm playing with spring security I didn't go for any database configuration. You can implement it in your own way. The above validates auth credentials and sets role(authorities). As admin can be able to view user modules as well(most cases, at least that's my conception), I've attached authorities user& admin when admin logs in. In simple words, 1. When a user log in he'll be able access every /** , but not /admin/** 2. When a admin log in he'll be able access every /** and /admin/**

I've tested the scenarios, and the entire code you can go though here - https://github.com/satya-j/rab

Upvotes: 0

Related Questions