L Tel
L Tel

Reputation: 67

Displaying username logged in using thymeleaf fragment header in Spring boot application

I have a fragment for my web application which is used across multiple pages to display a navbar with the user logged in : if they are logged in, if not : display login & signup button.

I want to know how to include my attribute of a logged in user to a fragment as currently I have the logged in user attribute mapped to each controller displaying a web page, not a fragment.

To get the current logged in user I use

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        model.addAttribute("loggedinuser", authentication.getName());

However this is only specific to one get request. I want to be able to display the logged in user in a fragment which is then called by each page.

Here is an example of a controller getting the logged in user

    @GetMapping(path= "")
    public String getMainPage(HttpServletRequest request, Model model) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        model.addAttribute("loggedinuser", authentication.getName());
        model.addAttribute("roles", authentication.getAuthorities());
        return "mainpage";
    }

Here is my class extending WebSecurityConfigurerAdapter to authenticate a users username and password against one in the database

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        String userbyUsernameQuery = "select username, password, '1' as enabled from auth_user where username=?;";
        String rolebyUsernameQuery = "SELECT auth_user.username, auth_role.role_name as authority from auth_user\n" +
                "INNER JOIN auth_user_role ON auth_user.auth_user_id = auth_user_role.auth_user_id\n" +
                "INNER JOIN auth_role ON auth_role.auth_role_id = auth_user_role.auth_role_id\n" +
                "WHERE auth_user.username =?";

        auth.jdbcAuthentication()
                .dataSource(dataSource)
                .usersByUsernameQuery(userbyUsernameQuery)
                .authoritiesByUsernameQuery(rolebyUsernameQuery)
                .passwordEncoder(passwordEncoder());


    }

The part of the navbarHeader fragment I want to change is this

        <ul class="nav navbar-nav navbar-right">
            <li><a th:href="@{/registration}"><span class="glyphicon glyphicon-user"></span>Sign up</a></li>
            <li><a th:href="@{/login}"><span class="glyphicon glyphicon-log-in"></span> Login</a></li>
        </ul>

I want to display the logged in user if logged in & disable the sign up button. If not then display the log in button & signup button

Here is my mainpage page which displays the current user logged in and role which I want to move to the fragment so I do not need to add all the code in each controller & html page.

<div align="right" id="loggedIn" th:if="${loggedinuser != null}">
    <div style="margin: 10px"
         th:text="'Logged in as: '+${loggedinuser} + ' Role: ' +${roles}">

    </div>
</div>

The user class

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User{

    private int id;

    private String name;

    private String lastName;

    private String username;

    private String password;

    private String email;

    private String enabled;

    public User(String name, Collection<? extends GrantedAuthority> authorities) {
    }
}

Upvotes: 1

Views: 2032

Answers (1)

Pasupathi Rajamanickam
Pasupathi Rajamanickam

Reputation: 2052

For this issue I basically utilize ModelAttribute which would be available across all the Presentation compilation. So your controller would like this

public class MyController {

    @GetMapping(path= "hi")
    public String getMainPage(HttpServletRequest request, Model model) {
        return "mainpage";
    }

    @GetMapping(path= "hello")
    public String getMainPage(HttpServletRequest request, Model model) {
        return "helloPage";
    }

    @ModelAttribute("loggedinuser")
    public User globalUserObject() {
        // Add all null check and authentication check before using. Because this is global 
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        model.addAttribute("loggedinuser", authentication.getName());
        model.addAttribute("roles", authentication.getAuthorities());
        // Create User pojo class
        User user = new User(authentication.getName(), Arrays.asList(authentication.getAuthorities()))
        return user;
    }
}

Now the object loggedinuser available for all the pages.

Upvotes: 1

Related Questions