Spring Security Integration issue

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Spring Security Integration issue

chinesco
Hello,

I just started using Thyme and my first app with a regular configuration works great, now I am trying to integrate it with Spring Security and have the following issue.

My original Template configuration does define the suffix property:

<bean id="templateResolver"
                class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
                <property name="suffix" value=".html" /> ....

In the Security config example, the suffix property is not defined.  Now if I remove it, all the security flow works fine but my original RequestMappings are then not resolved anymore

One sample of my existing mappings is as follows, where register is a valid template file with the name register.html:

        @RequestMapping(value = "/register", method = RequestMethod.GET)
        public String registerForm() {
                return "register";
        }

The error I get in this case is:  
TemplateEngine (TemplateEngine.java:1173) - [THYMELEAF][http-bio-8080-exec-6] Exception processin
g template "register": Error resolving template "register", template might not exist or might not be accessible by any of the configured Template Reso
lvers


If on the other hand, I keep the suffix property, all my original mappings work fine but none of the security templates are found.  I am using the mappings right from the sample app, so one of the mappings for the security portion is:

    /** Login form. */
    @RequestMapping("/login.html")
    public String login() {
        return "login.html";
    }

The error in this case is something like:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: Error resolving template "login.html", template might not exist or might not be accessible by any of the configured Template Resolvers

I am pretty sure is something I am doing wrong in the configuration but not sure where, any help is appreciated.

Thanks.
Reply | Threaded
Open this post in threaded view
|

Re: Spring Security Integration issue

chinesco
Hello,

I just figured it out myself, it was because my Controller was returning the template values with the extensions, so instead of:

 /** Login form. */
    @RequestMapping("/login.html")
    public String login() {
        return "login.html";
    }

Now I have:

    /** Login form. */
    @RequestMapping("/login")
    public String login() {
        return "login";
    }

and my config file is still the same:

        <bean id="templateResolver"
                class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
                <property name="prefix" value="/WEB-INF/templates/" />
                <property name="suffix" value=".html" />
                <property name="templateMode" value="HTML5" />
                  ....
        </bean>

Thanks.
Reply | Threaded
Open this post in threaded view
|

Re: Spring Security Integration issue

blandger
I also have a question about thymeleaf usage with Spring Security.
Probably it's not strictly related to security, more to thymeleaf usage itself.

How is better translate following jstl constuction into thymeleaf template code:
...........
    <sec:authorize var="loggedIn" access="isAuthenticated()"/>
    <c:set var="isDisabled" value=""/>
    <c:if test="${!loggedIn}">
        <c:set var="isDisabled" value="disabled"/>
    </c:if>

    <div class="button-bar">
        <button ${isDisabled}><spring:message code="menu.actions.item.events"/></button>
        <button ${isDisabled}><spring:message code="menu.actions.item.intents"/></button>
        <button ${isDisabled}><spring:message code="menu.actions.item.invitation"/></button>
        <button ${isDisabled}><spring:message code="menu.actions.item.actions"/></button>
    </div>
........
Code like:
<div sec:authorize="${isAuthenticated()}">
    <div class="button-bar">
        <button disabled="enabled">#{menu.actions.item.events}</button>
        <button ..........
.........
    </div>
</div>
<div>..... otherwise show buttons with DISABLED buttons...</div>
looks a bit ugly.

The main point, how is better to store variable value (loggedIn) and used it on template code below it?

Thanks
Reply | Threaded
Open this post in threaded view
|

Re: Spring Security Integration issue

danielfernandez
Administrator

Hi,

There is a "th:disabled" attribute that admits a boolean expression, and outputs "disabled="disabled"" if such expression evals to true, and nothing if it does eval to false.

So, you can do something like:

    <button th:disabled="${#authentication}">

...that would be equivalent to checking whether the "#authentication" object is null or not. If it is not null, your user is authenticated.

Regards,
Danie.
Reply | Threaded
Open this post in threaded view
|

Re: Spring Security Integration issue

danielfernandez
Administrator
Well, sorry, I imagine you would be disabling your button if the user is NOT authenticated, so:

    <button th:disabled="! ${#authentication}">

Regards,
Daniel.
Reply | Threaded
Open this post in threaded view
|

Re: Spring Security Integration issue

blandger
Thank you, Daniel for tips and great lib.
Reply | Threaded
Open this post in threaded view
|

Re: Spring Security Integration issue

blandger
Hi all, again.
I still can't understand how Spring Security tag works (or should work).
For example I don't see correct work for th:switch tag in that case. May be the reason is - http://www.thymeleaf.org/whatsnew20.html#dtds  ) ???

In any case I have Java Web config configuration with added SpringSecurity dialect.

    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(this.templateResolver());
        templateEngine.setTemplateEngineMessageSource(this.messageSource());

        org.thymeleaf.extras.tiles2.dialect.TilesDialect tilesDialect = new org.thymeleaf.extras.tiles2.dialect.TilesDialect();
        templateEngine.addDialect(tilesDialect);
        SpringSecurityDialect springSecurityDialect = new SpringSecurityDialect();
        templateEngine.addDialect(springSecurityDialect);
        ConditionalCommentsDialect conditionalCommentsDialect = new ConditionalCommentsDialect();
        templateEngine.addDialect(conditionalCommentsDialect);
        return templateEngine;
    }

I'd like to make displaying UI components using: IF  - THEN - ELSE  approach, but I don't see th:switch works as expected.
I created following test code in HTML (code is screwed up a little for displaying it on forum):


    <div th:if="${#authentication}">
        Logged - 1
    </div>
    <div th:unless="${! #authentication.authenticated}">
        Not Logged - 1
    </div>

    <div th:if="${#authorization.expression('isAuthenticated()') == true}">
        Logged - 2
    </div>
    <div th:unless="${#authorization.expression('isAuthenticated()') == false}">
        Not Logged - 2
    </div>

    result = < span th:text="${#authorization.expression('isAuthenticated()')}">< /span>
    <div th:switch="${#authorization.expression('isAuthenticated()')}">
        < span th:case="'true'">Logged (TRUE) - 3< /span>
        < span th:case="'false'">Not Logged (FALSE) - 3< /span>
        < span th:case="''">Not Logged (EMPTY) - 3< /span>
        < span th:case="*">Ops....!! (WHAT???) - 3< /span>
    </div>

Listing for LOGGED IN user:
-----------------------
Logged - 1
Not Logged - 1
Logged - 2
Not Logged - 2
result = true
Ops....!! (WHAT???) - 3

Listing for NOT LOGGED IN user:
--------------------------
Logged - 1
Not Logged - 1
result = false
Ops....!! (WHAT???) - 3

Did I miss something?


Now I decided to stay with following working approach:
    <div th:switch="${#authentication.name}">
        < span th:case="'anonymousUser'">Not Logged (FALSE)< /span>
        < span th:case="*">Logged IN (TRUE)< /span>
    </div>

Can someone explain behavior?
Reply | Threaded
Open this post in threaded view
|

Re: Spring Security Integration issue

Emanuel
Administrator
You can put code inside <raw></raw> tags so that the forum doesn't mess with it.

For the switch statement, I think you're getting unexpected results because you're case statements are the strings "true"/"false" instead of the boolean values of true/false.  I was able to get the expected results by changing them to:

<div th:switch="${#authorization.expression('isAuthenticated()')}">
  <span th:case="${true}">Logged (TRUE) - 3</span>
  <span th:case="${false}">Not Logged (FALSE) - 3</span>
  <span th:case="*">Ops....!! (WHAT???) - 3</span>
</div>
Reply | Threaded
Open this post in threaded view
|

Re: Spring Security Integration issue

blandger
Thank you Emanuel.
I'll give it one more try tomorrow. I'm suspect your code should work fine.
Reply | Threaded
Open this post in threaded view
|

Re: Spring Security Integration issue

blandger
This post was updated on .
In reply to this post by Emanuel
Emanuel, you are completely right.
I switched to that implementation.

Also I found that the solution for 'disabled' attribute proposed by Daniel
<button th:disabled="${#authentication}">.....
 works a bit worse for my opinion then that one:
<button th:disabled="${#authorization.expression('isAuthenticated()')}" th:value="#{menu.item.bla-bla-bla}">My menu</button>

Only thing worries me... It's not directly related to thymleaf, but...
When I click 'cancel' action on my web-flow page and redirect logged in (or anonymous) user to home/root page (/index) I'm loosing 'authentication information'. I saw that behavior on JSPs before and continue see that with thymeleaf.

When I have logged in user and web-flow is started, the expression like:
Logged In? = <snap th:text="${#authentication}"></snap>
gives me correct object of 'UsernamePasswordAuthenticationToken':
Logged In? =   org.springframework.security.authentication.UsernamePasswordAuthenticationToken......

But then I'm landing 'home' on web-flow cancelling, url like:
.../index?flowExecutionKey=e5s1&flowExecutionUrl=%2Fevent%2Fregister%3Fexecution%3De5s1
I have expression above evaluated to 'empty': Logged In? =


If I try to work around by expression like:
....th:disabled="${#authorization.authentication}? ${#authorization.expression('isAuthenticated()')} : ${false}"......
it produces error like:
........TemplateProcessingException: Exception evaluating SpringEL expression: "#authorization.expression('isAuthenticated()')" (include/header
.....
java.lang.IllegalArgumentException: Authentication object cannot be null
......

So I modified it like that:
.......th:disabled="${#authentication}? ${#authorization.expression('isAuthenticated()')} : ${false}"
mixing #authentication and #authorization.expression... in one expression.


It's a little dumb and needs more research, but it's fine for now in order do not stop.
I suppose something is strange (or wrong) with Web-Flow part.
That worries me because I don't have something unusual in web-flow description and configuration
<view-state id="........
    <transition on="cancel" to="registrationCancelled" bind="false" />
</view-state>
.....
<end-state id="registrationCancelled" view="redirect:/index"/>