Unable to hide links based on security

Viewed 3257

I am trying to show links only if the user role is permitted. But the links are not hidden and everything is shown for any roles.

Seen so many similar queries here and none of the solution is working. Please advice what I'm missing.

Configs.

@Configuration
@EnableWebSecurity
public class SecConfig extends WebSecurityConfigurerAdapter{

    private final String USER = "USER";
    private final String ADMIN = "ADMIN";

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/").hasAnyRole(USER, ADMIN)
                .antMatchers("/closed").hasRole(ADMIN).and()
                .formLogin().defaultSuccessUrl("/");
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("jane").password(passwordEncoder().encode("qwe")).roles(ADMIN, USER).and()
                .withUser("john").password(passwordEncoder().encode("qwe")).roles(USER);
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

POM

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

HTML

<a th:href="@{/closed}">Go to closed</a>

<br/><br/>

<form th:action="@{/logout}" method="post">
    <input type="submit" value="Log out">
</form>

<br/>

<h2>Welcome</h2>
<p>Spring Security Thymeleaf</p>
<div sec:authorize="hasRole('USER')">Text visible to user.</div>
<div sec:authorize="hasRole('ADMIN')">Text visible to admin.</div>
<div sec:authorize="isAuthenticated()">
    Text visible only to authenticated users.
</div>
Authenticated username:
<div sec:authentication="name"></div>
Authenticated user roles:
<div sec:authentication="principal.authorities"></div>

Everything above is displayed for Jane even though she has no admin access. Plus even her roles and username is not displayed either.

I also tried configuring the dialect as follows which makes no difference.

@Configuration
public class LeafConfig {

    @Bean
    public SpringSecurityDialect springSecurityDialect(){
        return new SpringSecurityDialect();
    }
}

The following is whats displayed for Jane or John., No difference:

Welcome
Spring Security Thymeleaf

Text visible to user.
Text visible to admin.
Text visible only to authenticated users.
Authenticated username:
Authenticated user roles:
2 Answers

Since you are using Spring Security extras, you could instead of sec:authorization try using ${#authorization.expression('hasRole(''ROLE_ADMIN'')'}. For example.

<div th:if="${#authorization.expression('hasRole(''USER'')'}">Text visible to user.</div>
<div th:if="${#authorization.expression('hasRole(''ADMIN'')'}">Text visible to admin.</div>
<div th:if="${#authorization.expression('isAuthenticated()')}">
    Text visible only to authenticated users.
</div>

In case you use authorities instead of roles, the following code will do the trick.

<div th:if="${#authorization.expression('hasAuthority(''ADMIN'')')}">ADMIN</div>
     <div th:if="${#authorization.expression('hasAuthority(''USER'')')}">USER</div>
     <div th:if="${#authorization.expression('isAuthenticated()')}">
         Text visible only to authenticated users.
     </div>
</div>

Regarding your con figuration, change your org.thymeleaf.extras for thymeleaf-extras-springsecurity5 in your .pom and you need to add the Spring Dialect @Bean to your configuration.

POM

<dependencies>
    ...
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity5</artifactId>
    </dependency>
    ...
</dependencies>

LeafConfig

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect;

@Configuration
public class LeafConfig {

    @Bean
    public SpringSecurityDialect springSecurityDialect(){
        return new SpringSecurityDialect();
    }

}

After these changes, everything should work as intended.

You should use it like below:

<sec:authorize access="hasRole('ADMIN')">
  <div>
    This content will only be visible to users who have
    the "ADMIN" authority in their list of GrantedAuthority's.
  </div>
</sec:authorize>

Related