コンテンツへスキップ

開発者ドキュメント

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

  • 投稿日: 2019-11-05 2019-11-05
  • タグ: custom login, Security, Spring Boot, Spring Security, template, 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.プロジェクトディレクトリ


image

プロジェクトの依存関係


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[

画像、幅= 1020、高さ= 621

]

6.3


http://localhost:8080/admin`にアクセスし、



http://localhost:8080/login`にリダイレクトします。



画像、幅= 1020、高さ= 621

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


http://localhost:8080/login

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

画像、幅= 1020、高さ= 621

]

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

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

画像、幅= 817、高さ= 538

]

6.6


http://localhost:8080/user`にアクセスし、



http://localhost:8080/403`にリダイレクトします。

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

画像、幅= 817、高さ= 538

]

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



画像、幅= 907、高さ= 610

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

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

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

spring-boot-spring-security-thymeleaf.zip

(15 KB)

参考文献


  1. Webアプリケーションのセキュリティ


  2. https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/

    [Spring

セキュリティリファレンス]。

https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-security

[Spring

ブートセキュリティ機能]。リンク://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

  • 標準URL構文]。

    https://medium.com/@gustavo.ponce.ch/spring-boot-spring-mvc-spring-security-mysql-a5d8545d837d

    [Spring

Boot + Spring MVC + Springセキュリティ+ MySQL]。

http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc-static-content

[Spring

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

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

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

spring boot


spring
セキュリティ

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

投稿ナビゲーション

前 前の投稿: SpringブートJDBC MySQL HikariCPの例
次 次の投稿: Hibernate – 1対多の例(注釈)

getdocs

13036RSS




タグ

Algorithms apache Applications CentOS Core Java Databases debian Development DevOps Docker Hibernate Java Java Collections javascript Let's Encrypt Linux Basics Maven Miscellaneous MongoDB Monitoring mysql Networking nginx Node.js NoSQL Persistence php Programming python React REST Security Spring Spring Boot Spring MVC Spring Security System Tools Testing ubuntu Ubuntu 16.04 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 18.04 Vue.js Weekly Review

最近の投稿

  • arpingコマンド
  • ターミナルからプロセスを完全に切り離す
  • iPerfを使用してネットワークパフォーマンスを測定する方法
  • コマンドラインからLinuxディストリビューションを探す
  • パブリックDMZネットワークアーキテクチャ

60日間無料の$100ドルのクレジットを取得

60日間無料の$100ドルのクレジットを取得

© 2025  開発者ドキュメント. Proudly powered by WordPress. WordStar, Theme by Linesh Jose

モバイルバージョンに移動