DEV Community

Salad Lam
Salad Lam

Posted on

How thymeleaf processes value of "sec:authorize" attribute (Spring Security integration module)

Notice

I wrote this article and was originally published on Qiita on 3 September 2019.


Package used

  • spring-webmvc-5.1.9.RELEASE
  • thymeleaf-3.0.11.RELEASE
  • thymeleaf-spring5-3.0.11.RELEASE
  • thymeleaf-extras-springsecurity5-3.0.4.RELEASE

How?

First look into following code which extract from guide from thymeleaf.

<div sec:authorize="isAuthenticated()">
  This content is only shown to authenticated users.
</div>
<div sec:authorize="hasRole('ROLE_ADMIN')">
  This content is only shown to administrators.
</div>
<div sec:authorize="hasRole('ROLE_USER')">
  This content is only shown to users.
</div>
Enter fullscreen mode Exit fullscreen mode

Attribute value of "sec:authorize" is handle by class org.thymeleaf.extras.springsecurity5.dialect.processor.AuthorizeAttrProcessor

public final class AuthorizeAttrProcessor extends AbstractStandardConditionalVisibilityTagProcessor {

    @Override
    protected boolean isVisible(
            final ITemplateContext context, final IProcessableElementTag tag,
            final AttributeName attributeName, final String attributeValue) {

        final String attrValue = (attributeValue == null? null : attributeValue.trim());

        if (attrValue == null || attrValue.length() == 0) {
            return false;
        }

        final Authentication authentication = AuthUtils.getAuthenticationObject(context);

        if (authentication == null) {
            return false;
        }

        return AuthUtils.authorizeUsingAccessExpression(context, attrValue, authentication);

    }
    // ...
}
Enter fullscreen mode Exit fullscreen mode

Attribute value of "sec:authorize" will be processed by SpEL

This code

<div sec:authorize="isAuthenticated()">
  This content is only shown to authenticated users.
</div>
Enter fullscreen mode Exit fullscreen mode

have the same meaning of

<div sec:authorize="${isAuthenticated()}">
  This content is only shown to authenticated users.
</div>
Enter fullscreen mode Exit fullscreen mode

due to text between brackets will be extract by org.thymeleaf.extras.springsecurity5.auth.AuthUtils.MvcAuthUtils.authorizeUsingAccessExpressionMvc(IExpressionContext, String, Authentication) before pass to SpEL.

    private static final class MvcAuthUtils {

        private static boolean authorizeUsingAccessExpressionMvc(
                final IExpressionContext context,
                final String accessExpression, final Authentication authentication) {

            /*
             * In case this expression is specified as a standard variable expression (${...}), clean it.
             */
            final String expr =
                    ((accessExpression != null && accessExpression.startsWith("${") && accessExpression.endsWith("}"))?
                            accessExpression.substring(2, accessExpression.length() - 1) :
                            accessExpression);
            // ...

            // pass to SpEL
            return (ExpressionUtils.evaluateAsBoolean(expressionObject, wrappedEvaluationContext));
        }
        // ...
    }
Enter fullscreen mode Exit fullscreen mode

isAuthenticated() and hasRole() is function of class org.springframework.security.web.access.expression.WebSecurityExpressionRoot

EvaluationContext used by SpEL is build from org.springframework.security.access.expression.AbstractSecurityExpressionHandler.createEvaluationContext(Authentication, T).

public abstract class AbstractSecurityExpressionHandler<T> implements
        SecurityExpressionHandler<T>, ApplicationContextAware {

    public final EvaluationContext createEvaluationContext(Authentication authentication,
            T invocation) {
        SecurityExpressionOperations root = createSecurityExpressionRoot(authentication,
                invocation);
        StandardEvaluationContext ctx = createEvaluationContextInternal(authentication,
                invocation);
        ctx.setBeanResolver(br);
        ctx.setRootObject(root);

        return ctx;
    }

    // ...
}
Enter fullscreen mode Exit fullscreen mode

Variable "root" is instance of class org.springframework.security.web.access.expression.WebSecurityExpressionRoot.

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay