Skip to content
Advertisement

Spring. One-time add session attributes after authorization

Stack: Spring Security and Thymeleaf.

I have the following problem: I want to show or not show some elements in all html templates depending on user’s role.

So, I need a boolean variable “isAdmin” in all templates so that I can use it in conditions:

<p th:if="${isAdmin}">Admin functionality</p>

Please help me find the best solution. What I tried:

Option 1. I can add variable to the model in all controllers. But I think it’s a bad practice.

Option 2. I can inject variable into the body with “th:with” directly from the session:

<body th:with="isAdmin=
    ${session
    .SPRING_SECURITY_CONTEXT
    .getAuthentication()
    .getAuthorities()
    .contains(T(com.example.model.enums.Role).ADMIN)}">

But it’s too long declaration. I also didn’t fin information about the scope of global variables in Thymeleaf.

Option 3. I understood I should add custom attribute in user session. And I should add it only one-time after authorization. I couldn’t think of something better than overriding successForwardUrl, adding attribute in new controller and redirecting to the main page.

.formLogin()
.loginPage("/login").permitAll()
.successForwardUrl("/login/setAttributes")
@PostMapping ("login/setAttributes")
public String postLoginPage(HttpSession httpSession) {
    boolean isAdmin = SecurityContextHolder
            .getContext()
            .getAuthentication()
            .getAuthorities()
            .contains(Role.ADMIN);

    httpSession.setAttribute("isAdmin", isAdmin);
    return "redirect:/";
}

But I still think it’s not the best solution.

Advertisement

Answer

Looks like you’re looking for the best solution

Thymeleaf has its special integration with Spring Security

You can check docs here

First of all, you should add org.thymeleaf.extras dependency to your project:

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

Next step. Add Thymeleaf sec namespace to your .html template:

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">

Finally, you can check user role and show specific content for different role:

<div sec:authorize="hasRole('ROLE_ADMIN')">
    <p>Admin functionality</p>
</div>

Also sec:authentication can be used to retrieve user name and roles:

<div sec:authorize="isAuthenticated()">
    User: <span sec:authentication="name">User name</span>
    Roles: <span sec:authentication="principal.authorities">User roles</span>
</div>
9 People found this is helpful
Advertisement