spring-bootspring-securitycsrftemplate-enginejte

Best way to automatically add CSRF Token to Spring Boot JTE main template


I like the new template engine JTE and I am trying to learn this.

I know I can manually add the CSRF token as a request attribute and I have done it for my login form like so:

@GetMapping("/login")
    public String login(Model model, CsrfToken token) {
        model.addAttribute("csrf", token.getToken());
        return "auth/login";
    }

@param String title
@param String csrf

@template.main-layout(title = title, content = @`
    <form action="/login" method="POST">
        <div>
            <input type="text" name="username" placeholder="Username: ">
        </div>
        <div>
            <input type="password" name="password" placeholder="Username: ">
        </div>
        <div>
            <input type="hidden" name="_csrf" value="${csrf}">
        </div>
        <div>
            <input type="submit" value="Log in" />
        </div>
    </form>
`)

But in my main layout file in my dummy project, I want to have a condition that basically checks if the user is authenticated, if yes, i want to display a logout button, otherwise a login link.

Now, I don't want to pass a CSRF token as a @param for each view, this would be annoying,

Is there a good way to implement this directly in the template ?

Otherwise i am happy to learn how to contribute to open source and try build this, Or I might just need to learn thymeleaf because i think it has this functionality out of the box


Solution

  • The best way I have found so far is to use @ControllerAdvice

        import org.springframework.security.web.csrf.CsrfToken;
        import org.springframework.ui.Model;
        import org.springframework.web.bind.annotation.ControllerAdvice;
        import org.springframework.web.bind.annotation.ModelAttribute;
        
        @ControllerAdvice
        public class JteControllerAdvice {
            
            @ModelAttribute
            public void csrf(Model model, CsrfToken csrf) {
                model.addAttribute("_csrf", csrf);
            }
        }
    

    You can also use @ControllerAdvice to only target specific Controllers.