thymeleaf / thymeleaf-extras-springsecurity

Thymeleaf "extras" integration module for Spring Security 3.x and 4.x
http://www.thymeleaf.org
Apache License 2.0
476 stars 107 forks source link

Thymeleaf - Spring Security integration modules

[Please make sure to select the branch corresponding to the version of Thymeleaf you are using]

Status

This is a Thymeleaf Extras module, not a part of the Thymeleaf core (and as such following its own versioning schema), but fully supported by the Thymeleaf team.

This repository contains 3 projects:

Current versions:

License

This software is licensed under the Apache License 2.0.

Requirements (3.0.x)

Maven info

Distribution packages

Distribution packages (binaries + sources + javadoc) can be downloaded from bintray.

Features

This module provides a new dialect called org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect or org.thymeleaf.extras.springsecurity6.dialect.SpringSecurityDialect (depending on the Spring Security version), with default prefix sec. It includes:

Configuration

In order to use the thymeleaf-extras-springsecurity[5|6] modules in our Spring MVC application (or thymeleaf-extras-springsecurity6 in a Spring WebFlux application), we will first need to configure our application in the usual way for Spring + Thymeleaf applications (TemplateEngine bean, template resolvers, etc.), and add the SpringSecurity dialect to our Template Engine so that we can use the sec:* attributes and special expression utility objects:

<bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
  ...
  <property name="additionalDialects">
    <set>
      <!-- Note the package would change to 'springsecurity[5]' if you are using that version -->
      <bean class="org.thymeleaf.extras.springsecurity6.dialect.SpringSecurityDialect"/>
    </set>
  </property>
...
</bean>

And that's all!

NOTE: If we are using Thymeleaf in a Spring Boot application, all that will be needed is to add the corresponding Thymeleaf and Spring Security starters to our application as well as the thymeleaf-extras-springsecurity[5|6] dependency, and this dialect will be automatically configured for us.

Using the expression utility objects

The #authentication object can be easily used, like this:

<div th:text="${#authentication.name}">
  The value of the "name" property of the authentication object should appear here.
</div>

The #authorization object can be used in a similar way, normally in th:if or th:unless tags:

<div th:if="${#authorization.expression('hasRole(''ROLE_ADMIN'')')}">
  This will only be displayed if authenticated user has role ROLE_ADMIN.
</div>

The #authorization object is an instance of org.thymeleaf.extras.springsecurity[5|6].auth.Authorization, see this class and its documentation to understand all the methods offered.

Using the attributes

Using the sec:authentication attribute is equivalent to using the #authentication object, but using its own attribute:

<div sec:authentication="name">
  The value of the "name" property of the authentication object should appear here.
</div>

The sec:authorize and sec:authorize-expr attributes are exactly the same. They work equivalently to a th:if that evaluated an #authorization.expression(...) expression, by evaluating a Spring Security Expression:

<div sec:authorize="hasRole('ROLE_ADMIN')">
  This will only be displayed if authenticated user has role ROLE_ADMIN.
</div>

These Spring Security Expressions in sec:authorize attributes are in fact Spring EL expressions evaluated on a SpringSecurity-specific root object containing methods such as hasRole(...), getPrincipal(), etc.

As with normal Spring EL expressions, Thymeleaf allows you to access a series of objects from them including the context variables map (the #vars object). In fact, you are allowed to surround your access expression with ${...} if it makes you feel more comfortable:

<div sec:authorize="${hasRole(#vars.expectedRole)}">
  This will only be displayed if authenticated user has a role computed by the controller.
</div>

Remember that Spring Security sets a special security-oriented object as expression root, which is why you would not be able to access the expectedRole variable directly in the above expression.

Another way of checking authorization is sec:authorize-url, which allows you to check whether a user is authorized to visit a specific URL or not:

<div sec:authorize-url="/admin">
  This will only be displayed if authenticated user can call the "/admin" URL.
</div>

For specifying a specific HTTP method, do:

<div sec:authorize-url="POST /admin">
  This will only be displayed if authenticated user can call the "/admin" URL
  using the POST HTTP method.
</div>

Finally, there is an attribute for checking authorization using Spring Security's Access Control Lists, which needs the specification of a domain object and the permissions defined on it that we are asking for.

<div sec:authorize-acl="${obj} :: '1,3'">
  This will only be displayed if authenticated user has permissions "1" and "3"
  on domain object referenced by context variable "obj".
</div>

In this attribute, both domain object and permission specifications are considered to be thymeleaf Standard Expressions.

Namespace

The namespace for all versions of this dialect is http://www.thymeleaf.org/extras/spring-security.

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

Getting the namespace incorrect won't impact processing of your template. It might however impact your IDE when it comes to things like suggestions/auto-completion in your templates.