I have a Spring + Thymeleaf project with the following view code.
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring3-3.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Contacts</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<div id="content">
<h1>Welcome to the site!</h1>
<p th:if="${loginError}">Wrong user or password</p>
<form th:action="@{/j_spring_security_check}" method="post">
<label for="j_username">Email address</label>:
<input type="text" id="j_username" name="j_username"/> <br/>
<label for="j_password">Password</label>:
<input type="password" id="j_password" name="j_password"/> <br/>
<input type="submit" value="Log in"/>
</form>
</div>
<div sec:authorize="isAuthenticated()">
User: <span sec:authentication="name">miquel</span>
</div>
</body>
</html>
The sec:authorize and sec:authentication attributes don't work as expected - the div is always shown, even if no user is logged in, and the span always reads "miquel".
Follows a relevant snippet from my controller class.
@RequestMapping(value = "/welcome.html")
public String wellcome() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
System.out.println("username: " + auth.getName());
return "home";
}
The println statement works as expected - if no user is logged in, it prints "anonymousUser", otherwise the username.
What am I doing wrong?
The @PreAuthorize annotation checks the given expression before entering the method, whereas the @PostAuthorize annotation verifies it after the execution of the method and could alter the result.
Spring Security provides method level security using @PreAuthorize and @PostAuthorize annotations. This is expression-based access control. The @PreAuthorize can check for authorization before entering into method. The @PreAuthorize authorizes on the basis of role or the argument which is passed to the method.
Understanding sec:authentication. The Spring Security Authentication interface exposes useful methods concerning the authenticated principal or authentication request. To access an authentication object withing Thymeleaf, we can simply use <div sec:authentication=”name”> or <div sec:authentication=”principal.
After comparing my application closely to the Thymeleaf & Spring Security demo applicaiton, I discovered the source of the error.
Apparently, in order for Thymeleaf to process the sec:authorize
and sec:authentication
attributes, you need to register SpringSecurityDialect
as an additional dialect of the template engine bean.
<bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<property name="additionalDialects">
<set>
<bean class="org.thymeleaf.extras.springsecurity3.dialect.SpringSecurityDialect" />
</set>
</property>
</bean>
This is surprising as there is no mention of that fact on the related Thymeleaf documentation page. I hope this helps others who will face the same issue in future.
In Spring Boot I just had to add the following dependency:
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With