開発者ドキュメント

Springブート+ Springセキュリティ+ Thymeleafの例

SpringブートThymeleafの例では、Spring Securityを使用してパス

/admin`と

/user`を保護します

使用される技術:

  1. 春のブート1.5.3.RELEASE

  2. Spring 4.3.8.RELEASE

  3. 春のセキュリティ4.2.2

  4. タイメレフ2.1.5.リリース

  5. Thymeleaf extras Spring Security4 2.1.3

  6. Tomcat埋め込み8.5.14

  7. Maven 3

  8. Java 8

1.プロジェクトディレクトリ



プロジェクトの依存関係


spring-boot-starter-security`を宣言すると、

SpringBoot + Spring Security` Webアプリケーションを開発するために必要なものがすべて得られます。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <artifactId>spring-boot-web-spring-security</artifactId>
    <packaging>jar</packaging>
    <name>Spring Boot Web Spring Security</name>
    <description>Spring Boot Web Spring Security Example</description>
    <url>/</url>
    <version>1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <!-- Spring Security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <!-- do you like thymeleaf? -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!-- optional, it brings userful tags to display spring security stuff -->
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        </dependency>

        <!-- hot swapping, disable cache for template, enable live reload -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- Optional, for bootstrap -->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>3.3.7</version>
        </dependency>

    </dependencies>
    <build>
        <plugins>
            <!-- Package as an executable jar/war -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

プロジェクトの依存関係を表示する:

$ mvn dependency:tree
[INFO]Scanning for projects...[INFO][INFO]------------------------------------------------------------------------[INFO]Building Spring Boot Web Spring Security 1.0[INFO]------------------------------------------------------------------------[INFO][INFO]--- maven-dependency-plugin:2.10:tree (default-cli) @ spring-boot-web-spring-security ---[INFO]org.springframework.boot:spring-boot-web-spring-security:jar:1.0[INFO]+- org.springframework.boot:spring-boot-starter-thymeleaf:jar:1.5.3.RELEASE:compile[INFO]|  +- org.springframework.boot:spring-boot-starter:jar:1.5.3.RELEASE:compile[INFO]|  |  +- org.springframework.boot:spring-boot-starter-logging:jar:1.5.3.RELEASE:compile[INFO]|  |  |  +- ch.qos.logback:logback-classic:jar:1.1.11:compile[INFO]|  |  |  |  \- ch.qos.logback:logback-core:jar:1.1.11:compile[INFO]|  |  |  +- org.slf4j:jcl-over-slf4j:jar:1.7.25:compile[INFO]|  |  |  +- org.slf4j:jul-to-slf4j:jar:1.7.25:compile[INFO]|  |  |  \- org.slf4j:log4j-over-slf4j:jar:1.7.25:compile[INFO]|  |  +- org.springframework:spring-core:jar:4.3.8.RELEASE:compile[INFO]|  |  \- org.yaml:snakeyaml:jar:1.17:runtime[INFO]|  +- org.springframework.boot:spring-boot-starter-web:jar:1.5.3.RELEASE:compile[INFO]|  |  +- org.springframework.boot:spring-boot-starter-tomcat:jar:1.5.3.RELEASE:compile[INFO]|  |  |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:8.5.14:compile[INFO]|  |  |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:8.5.14:compile[INFO]|  |  |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:8.5.14:compile[INFO]|  |  +- org.hibernate:hibernate-validator:jar:5.3.5.Final:compile[INFO]|  |  |  +- javax.validation:validation-api:jar:1.1.0.Final:compile[INFO]|  |  |  +- org.jboss.logging:jboss-logging:jar:3.3.1.Final:compile[INFO]|  |  |  \- com.fasterxml:classmate:jar:1.3.3:compile[INFO]|  |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.8.8:compile[INFO]|  |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.8.0:compile[INFO]|  |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.8.8:compile[INFO]|  |  +- org.springframework:spring-web:jar:4.3.8.RELEASE:compile[INFO]|  |  \- org.springframework:spring-webmvc:jar:4.3.8.RELEASE:compile[INFO]|  +- org.thymeleaf:thymeleaf-spring4:jar:2.1.5.RELEASE:compile[INFO]|  |  \- org.thymeleaf:thymeleaf:jar:2.1.5.RELEASE:compile[INFO]|  |     +- ognl:ognl:jar:3.0.8:compile[INFO]|  |     +- org.javassist:javassist:jar:3.21.0-GA:compile[INFO]|  |     \- org.unbescape:unbescape:jar:1.1.0.RELEASE:compile[INFO]|  \- nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:jar:1.4.0:compile[INFO]|     \- org.codehaus.groovy:groovy:jar:2.4.10:compile[INFO]+- org.springframework.boot:spring-boot-starter-security:jar:1.5.3.RELEASE:compile[INFO]|  +- org.springframework:spring-aop:jar:4.3.8.RELEASE:compile[INFO]|  |  \- org.springframework:spring-beans:jar:4.3.8.RELEASE:compile[INFO]|  +- org.springframework.security:spring-security-config:jar:4.2.2.RELEASE:compile[INFO]|  |  +- org.springframework.security:spring-security-core:jar:4.2.2.RELEASE:compile[INFO]|  |  \- org.springframework:spring-context:jar:4.3.8.RELEASE:compile[INFO]|  \- org.springframework.security:spring-security-web:jar:4.2.2.RELEASE:compile[INFO]|     \- org.springframework:spring-expression:jar:4.3.8.RELEASE:compile[INFO]+- org.thymeleaf.extras:thymeleaf-extras-springsecurity4:jar:2.1.3.RELEASE:compile[INFO]|  \- org.slf4j:slf4j-api:jar:1.7.25:compile[INFO]+- org.springframework.boot:spring-boot-devtools:jar:1.5.3.RELEASE:compile[INFO]|  +- org.springframework.boot:spring-boot:jar:1.5.3.RELEASE:compile[INFO]|  \- org.springframework.boot:spring-boot-autoconfigure:jar:1.5.3.RELEASE:compile[INFO]\- org.webjars:bootstrap:jar:3.3.7:compile[INFO]   \- org.webjars:jquery:jar:1.11.1:compile[INFO]------------------------------------------------------------------------[INFO]BUILD SUCCESS[INFO]------------------------------------------------------------------------[INFO]Total time: 2.072 s[INFO]Finished at: 2017-05-04T10:13:05+08:00[INFO]Final Memory: 19M/309M[INFO]------------------------------------------------------------------------

3.春のセキュリティ

3.1

WebSecurityConfigurerAdapter`を拡張し、

configure`メソッドでセキュリティルールを定義しました。

SpringSecurityConfig.java

package com.mkyong.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.access.AccessDeniedHandler;

@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AccessDeniedHandler accessDeniedHandler;

   //roles admin allow to access/admin/** **
   //roles user allow to access/user/** **
   //custom 403 access denied handler
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable()
                .authorizeRequests()
                    .antMatchers("/", "/home", "/about").permitAll()
                    .antMatchers("/admin/** ** ").hasAnyRole("ADMIN")
                    .antMatchers("/user/** ** ").hasAnyRole("USER")
                    .anyRequest().authenticated()
                .and()
                .formLogin()
                    .loginPage("/login")
                    .permitAll()
                    .and()
                .logout()
                    .permitAll()
                    .and()
                .exceptionHandling().accessDeniedHandler(accessDeniedHandler);
    }

   //create two users, admin and user
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        auth.inMemoryAuthentication()
                .withUser("user").password("password").roles("USER")
                .and()
                .withUser("admin").password("password").roles("ADMIN");
    }
}

3.2カスタム403アクセス拒否ハンドラは、要求を記録し、 `/403`にリダイレクトします。

WelcomeController.java

package com.mkyong.error;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//handle 403 page
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {

    private static Logger logger = LoggerFactory.getLogger(MyAccessDeniedHandler.class);

    @Override
    public void handle(HttpServletRequest httpServletRequest,
                       HttpServletResponse httpServletResponse,
                       AccessDeniedException e) throws IOException, ServletException {

        Authentication auth
                = SecurityContextHolder.getContext().getAuthentication();

        if (auth != null) {
            logger.info("User '" + auth.getName()
                    + "' attempted to access the protected URL: "
                    + httpServletRequest.getRequestURI());
        }

        httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/403");

    }
}

4.春のブート

4.1コントローラクラス。httpリクエストとビュー名を定義する。

DefaultController.java

package com.mkyong.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class DefaultController {

    @GetMapping("/")
    public String home1() {
        return "/home";
    }

    @GetMapping("/home")
    public String home() {
        return "/home";
    }

    @GetMapping("/admin")
    public String admin() {
        return "/admin";
    }

    @GetMapping("/user")
    public String user() {
        return "/user";
    }

    @GetMapping("/about")
    public String about() {
        return "/about";
    }

    @GetMapping("/login")
    public String login() {
        return "/login";
    }

    @GetMapping("/403")
    public String error403() {
        return "/error/403";
    }

}

4.2 Spring起動アプリケーションを起動します。

DefaultController.java

package com.mkyong;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootWebApplication {

    public static void main(String[]args) throws Exception {
        SpringApplication.run(SpringBootWebApplication.class, args);
    }

}

5. Thymeleafリソース静的ファイル

5.1 Thymeleafファイルの場合、 `src/main/resources/templates/`フォルダに入れます。

5.2テンプレートレイアウトのためのThymeleafフラグメント – ヘッダ。

src/main/resources/templates/fragments/header.html

<html xmlns:th="http://www.thymeleaf.org">
<head>
    <div th:fragment="header-css">
        <!-- this is header-css -->
        <link rel="stylesheet" type="text/css"
              href="webjars/bootstrap/3.3.7/css/bootstrap.min.css"/>

        <link rel="stylesheet" th:href="@{/css/main.css}"
              href="../../css/main.css"/>
    </div>
</head>
<body>
<div th:fragment="header">
    <!-- this is header -->
    <nav class="navbar navbar-inverse">
        <div class="container">
            <div class="navbar-header">
                <a class="navbar-brand" th:href="@{/}">Spring Boot</a>
            </div>
            <div id="navbar" class="collapse navbar-collapse">
                <ul class="nav navbar-nav">
                    <li class="active"><a th:href="@{/}">Home</a></li>
                </ul>
            </div>
        </div>
    </nav>
</div>

</body>
</html>

5.3テンプレートレイアウトのためのThymeleafフラグメント – フッター。 `sec`タグを確認してください。これはSpring Securityの情報を表示するのに便利なタグです。詳しくは、https://github.com/thymeleaf/thymeleaf-extras-springsecurity[Thymeleaf extra Spring Security]を参照してください。

src/main/resources/templates/fragments/footer.html

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
</head>
<body>
<div th:fragment="footer">

    <div class="container">

        <footer>
        <!-- this is footer -->
        © 2017 mkyong.com
            <span sec:authorize="isAuthenticated()">
                | Logged user: <span sec:authentication="name"></span> |
                Roles: <span sec:authentication="principal.authorities"></span> |
                <a th:href="@{/logout}">Sign Out</a>
            </span>

        <script type="text/javascript"
                src="webjars/bootstrap/3.3.7/js/bootstrap.min.js"></script>

        </footer>
    </div>

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

5.4 Thymeleafファイルのリスト。何も特別なものではなく、自明です。

ホーム〜

src/main/resources/templates/home.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Spring Boot Thymeleaf + Spring Security</title>

    <div th:replace="fragments/header :: header-css"/>

</head>
<body>

<div th:replace="fragments/header :: header"/>

<div class="container">

    <div class="starter-template">
        <h1>Spring Boot Web Thymeleaf + Spring Security</h1>
        <h2>1. Visit <a th:href="@{/admin}">Admin page (Spring Security protected, Need Admin Role)</a></h2>
        <h2>2. Visit <a th:href="@{/user}">User page (Spring Security protected, Need User Role)</a></h2>
        <h2>3. Visit <a th:href="@{/about}">Normal page</a></h2>
    </div>

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

<div th:replace="fragments/footer :: footer"/>

</body>
</html>

admin〜

src/main/resources/templates/admin.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <div th:replace="fragments/header :: header-css"/>
</head>
<body>

<div th:replace="fragments/header :: header"/>

<div class="container">

    <div class="starter-template">
        <h1>Admin page (Spring Security protected)</h1>

        <h1 th:inline="text">Hello[[${#httpServletRequest.remoteUser}]]!</h1>
        <form th:action="@{/logout}" method="post">
            <input type="submit" value="Sign Out"/>
        </form>

    </div>

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

<div th:replace="fragments/footer :: footer"/>

</body>
</html>

ユーザー〜

src/main/resources/templates/user.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <div th:replace="fragments/header :: header-css"/>
</head>
<body>

<div th:replace="fragments/header :: header"/>

<div class="container">

    <div class="starter-template">
        <h1>User page (Spring Security protected)</h1>

        <h1 th:inline="text">Hello[[${#httpServletRequest.remoteUser}]]!</h1>
        <form th:action="@{/logout}" method="post">
            <input type="submit" value="Sign Out"/>
        </form>

    </div>

</div>
<!--/.container -->
<div th:replace="fragments/footer :: footer"/>

</body>
</html>

約〜

src/main/resources/templates/about.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <div th:replace="fragments/header :: header-css"/>
</head>
<body>

<div th:replace="fragments/header :: header"/>

<div class="container">

    <div class="starter-template">
        <h1>Normal page (No need login)</h1>
    </div>

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

<div th:replace="fragments/footer :: footer"/>

</body>
</html>

ログイン〜

src/main/resources/templates/login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
>
<head>
    <title>Spring Security Example </title>
    <div th:replace="fragments/header :: header-css"/>
</head>
<body>

<div th:replace="fragments/header :: header"/>

<div class="container">

    <div class="row" style="margin-top:20px">
        <div class="col-xs-12 col-sm-8 col-md-6 col-sm-offset-2 col-md-offset-3">
            <form th:action="@{/login}" method="post">
                <fieldset>
                    <h1>Please Sign In</h1>

                    <div th:if="${param.error}">
                        <div class="alert alert-danger">
                            Invalid username and password.
                        </div>
                    </div>
                    <div th:if="${param.logout}">
                        <div class="alert alert-info">
                            You have been logged out.
                        </div>
                    </div>

                    <div class="form-group">
                        <input type="text" name="username" id="username" class="form-control input-lg"
                               placeholder="UserName" required="true" autofocus="true"/>
                    </div>
                    <div class="form-group">
                        <input type="password" name="password" id="password" class="form-control input-lg"
                               placeholder="Password" required="true"/>
                    </div>

                    <div class="row">
                        <div class="col-xs-6 col-sm-6 col-md-6">
                            <input type="submit" class="btn btn-lg btn-primary btn-block" value="Sign In"/>
                        </div>
                        <div class="col-xs-6 col-sm-6 col-md-6">
                        </div>
                    </div>
                </fieldset>
            </form>
        </div>
    </div>

</div>

<div th:replace="fragments/footer :: footer"/>

</body>
</html>

403〜

src/main/resources/templates/error/403.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <div th:replace="fragments/header :: header-css"/>
</head>
<body>

<div th:replace="fragments/header :: header"/>

<div class="container">

    <div class="starter-template">
        <h1>403 - Access is denied</h1>
        <div th:inline="text">Hello '[[${#httpServletRequest.remoteUser}]]',
                you do not have permission to access this page.</div>
    </div>

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

<div th:replace="fragments/footer :: footer"/>

</body>
</html>

5.5 CSSやJavascriptのような静的ファイルの場合、 `/src/main/resources/static/`に入れます。

/src/main/resources/static/css/main.css

h1{
    color:#0000FF;
}

h2{
    color:#FF0000;
}

footer{
    margin-top:60px;
}
  • 注** +これを理解するには、http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc-static-content[Spring Boot static static content]をお読みください。リソースマッピング。

6.デモ

6.1 Spring起動Webアプリケーションを起動します。この `/admin/


`は保護されており、アクセスするにはadminとしてログインする必要があります。

ターミナル

$ mvn spring-boot:run
//...

6.2 `http://localhost:8080`にアクセスします。

リンク://wp-content/uploads/2017/05/spring-boot-spring-security-1.png[



]

6.4不正なユーザ名またはパスワード


http://localhost:8080/login

リンク://wp-content/uploads/2017/05/spring-boot-spring-security-3.png[



]

6.5ログインに成功し、管理ページ `http://localhost:8080/admin`にリダイレクトし、フッターセクションを見直すと、ユーザー情報が表示されます。

リンク://wp-content/uploads/2017/05/spring-boot-spring-security-4.png[



]

リンク://wp-content/uploads/2017/05/spring-boot-spring-security-5.png[



]

6.7フッター内のサインアウトリンクをクリックし、 `http://localhost:8080/login?logout`にリダイレクトします。

完了しました。別のユーザ名 “user”でログインし、管理ページにアクセスしてください。

ソースコードをダウンロードする

それをダウンロードする –

spring-boot-spring-security-thymeleaf.zip

(15 KB)

参考文献

ブートセキュリティ機能]。リンク://spring-boot/spring-boot-hello-world-example-thymeleaf/[Spring

ブートHello Worldの例 – Thymeleaf]。リンク://spring-security/spring-security-hello-world-annotation-example/[Spring

セキュリティHello Worldの注釈の例]。

http://www.thymeleaf.org/doc/articles/springsecurity.html

[Thymeleaf –

Spring Securityの統合の基礎]。

https://github.com/thymeleaf/thymeleaf-extras-springsecurity

[Thymeleaf

特別なSpring Securityの統合の基礎]。

http://www.thymeleaf.org/doc/articles/standardurlsyntax.html

[Thymeleaf

ブート – 静的コンテンツ]。リンク://spring-mvc/spring-mvc-how-to-include-js-or-css-files-in-a-jsp-page/[Spring

MVC – CSSファイルを含める]

リンク://タグ/カスタムログイン/[カスタムログイン]リンク://タグ/セキュリティ/[セキュリティ]

spring boot


spring
セキュリティ

リンク://タグ/テンプレート/[テンプレート]リンク://tag/thymeleaf/[thymeleaf]

モバイルバージョンを終了