pooya
pooya

Reputation: 135

Spring security doesn't match a given role

I am developing a simple spring security app that has 3 user roles(emp,admin,man). I read user data by datasource and also i have my own access-denied page for the situation that any user wants to access to forbidden pages. before I used to define my user information(username, password, roles) on my java class DemoSecurityConfig in the method protected void configure () and spring security could notice what page each user can access but the problem is that since I am reading the information from the database all my users directed to the access denied page which means spring security roles don't work or it can't read the given role

DemoSecurityConfig class

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = "com")
public class DemoSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
   private DataSource securityDataSource;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       //use jdbc
        auth.jdbcAuthentication().dataSource(securityDataSource);

    }
    //configure of web patch in application login logout

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/").hasAnyRole("emp")
        .antMatchers("/leaders/**").hasAnyRole("man")
                .antMatchers("/systems/**").hasAnyRole("admin")
                .and().formLogin().loginPage("/showMyLoginPage")
                .loginProcessingUrl("/authenticateTheUser")
                .permitAll().and().logout().permitAll().and().exceptionHandling().accessDeniedPage("/access-denied");
    }

}

DemoAppConfig

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com")
@PropertySource("classpath:persistence-mysql.properties")
public class DemoAppConfig  {
    //define a bean for view resolver
    @Bean
   public ViewResolver viewResolver(){
      InternalResourceViewResolver viewResolver=new InternalResourceViewResolver();
      viewResolver.setPrefix("/WEB-INF/view/");
      viewResolver.setSuffix(".jsp");
      return  viewResolver;
    }
        //reading properties file

    //set yp varible for holding a properties
    @Autowired
    private Environment env;
    private Logger logger=Logger.getLogger(getClass().getName());
    //define a bean for data source

    @Bean
    public DataSource securityDataSource(){
    //create data connection
        ComboPooledDataSource securityDataSource
                =new ComboPooledDataSource();
        //set up jdbc driver class
        try {
            securityDataSource.setDriverClass(env.getProperty("jdbc.driver"));
        } catch (PropertyVetoException exc) {
            throw  new RuntimeException(exc);
        }
        //log the connection for make sure
       logger.info(">> jdbc.url=" +env.getProperty("jdbc.url"));
        logger.info(">> jdbc.user=" +env.getProperty("jdbc.user"));
        //set up database connection properties
securityDataSource.setJdbcUrl(env.getProperty("jdbc.url"));
        securityDataSource.setUser(env.getProperty("jdbc.user"));
        securityDataSource.setPassword(env.getProperty("jdbc.password"));
        //set yp connection props
        securityDataSource.setInitialPoolSize(getIntProperty("connection.pool.initialPoolSize"));
        securityDataSource.setMinPoolSize(getIntProperty("connection.pool.minPoolSize"));
        securityDataSource.setMaxPoolSize(getIntProperty("connection.pool.maxPoolSize"));
        securityDataSource.setMaxIdleTime(getIntProperty("connection.pool.maxIdleTime"));




        return securityDataSource;
    }
//need a helper class
    //read env property and convert to int
    private int getIntProperty(String proName){
        String proVal=env.getProperty(proName);
        int intPropVal=Integer.parseInt(proVal);
                return intPropVal;
    }

}

home.jsp

<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>this is a main page</h1>
<!-- add link to point to leaders   -->
<security:authorize access="hasRole('admin')">
<p>
    <a href="${pageContext.request.contextPath}/systems">IT meeting</a>
    (only for admins)
</p>
<br/>
<p>

    </security:authorize>
    <security:authorize access="hasRole('man')">
    <a href="${pageContext.request.contextPath}/leaders">leaders meeting</a>
    (only for admins)
</p>
<br/>
</security:authorize>
<form:form action="${pageContext.request.contextPath}/logout"  method="post">
    <input type="submit" value="Logout">

    <hr>
        <-- display user -->
    User: <security:authentication property="principal.username"/>
    <br><br>
    roles <security:authentication property="principal.authorities"/>

    </hr>

</form:form>
</body>
</html>

enter image description here

Upvotes: 0

Views: 1883

Answers (1)

Ken Chan
Ken Chan

Reputation: 90447

From the hasAnyRole() javadoc :

Shortcut for specifying URLs require any of a number of roles. If you do not want to have "ROLE_" automatically inserted see hasAnyAuthority(String...)

So hasAnyRole("emp") expects the user has the role ROLE_emp but the user has the role emp now .

Either update all user authorities in database to be prefixed with ROLE_ such as ROLE_emp and ROLE_admin or change to use hasAnyAuthority() which will not add the ROLE_ prefix :

    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/").hasAnyAuthority("emp")
            .antMatchers("/leaders/**").hasAnyAuthority("man")
            .antMatchers("/systems/**").hasAnyAuthority("admin")
            ......

    }

Upvotes: 2

Related Questions