Ich benutze Spring Boot, Spring Security und Thymeleaf. Derzeit funktionieren Authentifizierung und Autorisierung beim Zugriff auf Seiten einwandfrei, aber ich kann die Thymeleaf-Autorisierung nicht zum Funktionieren bringen. Der Ablauf ist sehr einfach: Ich versuche, auf die Seite admin.html zuzugreifen, für die ich die Rolle 'ADMIN' haben muss. Spring Security fängt die Anfrage korrekt ab, leitet mich zuerst an die Anmeldeseite weiter und wenn ich als Administrator angemeldet bin, kann ich fortfahren.

Jetzt möchte ich einige Inhalte auf der Administrationsseite basierend auf Rollen "verstecken". Auf meiner admin.html-Seite habe ich also Folgendes:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:include="header :: common-header">
    <title>Admin Page</title>
</head>

<body>

<div th:replace="navbar :: common-navbar"></div>

<div class="container">

    <div class="row">

        <div class="col-md-6 col-md-offset-3">

            <div class="well">

                <div th:if="${#authorization.expression('hasRole(''ROLE_ADMIN'')')}">
                    Secret Content
                </div>

                <div class="starter-template">
                    <h1>Hello Administrator!</h1>
                    <p class="lead">This page allows you to perform administrative tasks</p>
                    <form id="f" th:action="@{/logout}" method="post" role="form" class="form-group">
                        <input type="submit" value="Logout" class="btn btn-primary" />
                    </form>
                </div>

            </div>

        </div>

    </div>

</div><!-- /.container -->

<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<div th:include="header :: before-body-script">

</div>
</body>
</html>

Meine pom.xml:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.1.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>


    <!-- Thymeleaf Dialect -->
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        <version>3.0.0.BETA01</version>
    </dependency>

Meine Sicherheitskonfigurationsklasse:

@Override
protected void configure(HttpSecurity http) throws Exception {

    // Allows for static content
    http.authorizeRequests().antMatchers("/webjars/**").permitAll();
    http.authorizeRequests().antMatchers("/css/**").permitAll();
    http.authorizeRequests().antMatchers("/js/**").permitAll();

    // Defines security for everything else
    http
            .authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/admin").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
            .formLogin().loginPage("/login").failureUrl("/login?error").permitAll()
                .and()
            .logout()
                .permitAll();

}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
            .inMemoryAuthentication()
            .withUser("user").password("password").roles("USER")
            .and()
            .withUser("admin").password("admin").roles("USER", "ADMIN");
}

Ich habe viele Stunden lang versucht, dieses Problem zu lösen, aber ohne Erfolg. Natürlich könnte ich die Verwendung von Spring Boot vermeiden und JSPs anstelle von Thymeleaf verwenden, aber ich mag die Kombination aus Spring Boot + Spring Security + Thymeleaf sehr, da es näher an sauberem HTML liegt.

Ich habe auch versucht, das sec-Element wie im folgenden Snippet zu verwenden:

  <div sec:authorize="hasRole('ROLE_ADMIN1')">
      This content is only shown to administrators.
  </div>

Obwohl es keinen Fehler gibt, zeigt es den geheimen Inhalt für jede Rolle, auch für nicht vorhandene.

Ich habe versucht, eine SpringTemplateEngine durch Hinzufügen des SpringSecurityDialect zu definieren, aber es wurde eine Fehlermeldung angezeigt, dass ich sie zweimal deklariert habe (dies liegt vermutlich an der Maven-Abhängigkeit von der Extras-Bibliothek).

Ich würde mich wirklich über Hilfe freuen, bitte.

1
Marco Tedone 26 Dez. 2015 im 21:16

2 Antworten

Beste Antwort

Behoben durch Ändern der folgenden Abhängigkeit in pom.xml:

 <!-- Thymeleaf Dialect -->
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        <version>2.1.2.RELEASE</version>
    </dependency>

Anstelle von 3.0.0.BETA01. Nun funktioniert folgendes:

<div sec:authorize="hasRole('ROLE_ADMIN')">
                    This content is only shown to administrators.
                </div>
3
Marco Tedone 26 Dez. 2015 im 19:16

Es kann vorkommen, dass Sie vergessen haben, einen Ihrer Controller mit einer @Controller - Anmerkung zu markieren. Es ist in meinem Fall passiert und die Behebung hat dazu beigetragen, den Fehler zu beheben. Dies kann einer der Schritte zur Fehlerbehebung sein.

Dies liegt daran, dass der Controller, wenn Sie ihn nicht mit @controller markieren und versuchen, eine Referenz aus der Vorlagensprache (in meinem Fall Thymeleaf) zu erstellen, zur Laufzeit in den Kontext greift und das Authentifizierungsobjekt verliert daher der Fehler ungefähr so:

Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "#authorization.expression('!isAuthenticated()')" (template: "fragments/layout" - line 64, col 8)
    at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393)
    at org.attoparser.MarkupParser.parse(MarkupParser.java:257)
    at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230)
    ... 47 more
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "#authorization.expression('!isAuthenticated()')" (template: "fragments/layout" - line 64, col 8)
    at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:290)
...
...
...
...
... 49 more
Caused by: java.lang.IllegalArgumentException: Authentication object cannot be null
    at org.springframework.security.access.expression.SecurityExpressionRoot.<init>(SecurityExpressionRoot.java:61)

Bitte lassen Sie mich wissen, ob es funktioniert!

0
3AK 16 Dez. 2018 im 06:16