Open2

SpringSecutiryを入れたらデフォルトでBasic認証がかかって驚いた件

ふじしろふじしろ

spring initializrでSpringSecutiryを入れてプロジェクトを作成し、試しにhelloworldを作って動作確認したらいきなり認証を求められてビビったのでメモ

参考:当時の:build.gradle.kts
# build.gradle.kts
plugins {
	kotlin("jvm") version "1.9.25"
	kotlin("plugin.spring") version "1.9.25"
	id("org.springframework.boot") version "3.3.4"
	id("io.spring.dependency-management") version "1.1.6"
	kotlin("plugin.jpa") version "1.9.25"
}

group = "com.example"
version = "0.0.1-SNAPSHOT"

java {
	toolchain {
		languageVersion.set(JavaLanguageVersion.of(17))
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation("org.springframework.boot:spring-boot-starter-data-jpa")
	implementation("org.springframework.boot:spring-boot-starter-security")
	implementation("org.springframework.boot:spring-boot-starter-web")
	implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
	implementation("org.jetbrains.kotlin:kotlin-reflect")
	runtimeOnly("com.h2database:h2")
	testImplementation("org.springframework.boot:spring-boot-starter-test")
	testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
	testImplementation("org.springframework.security:spring-security-test")
	testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

kotlin {
	compilerOptions {
		freeCompilerArgs.addAll("-Xjsr305=strict")
	}
}

tasks.withType<Test> {
	useJUnitPlatform()
}
参考:当時のプロジェクトツリー
src
├── main
│   ├── kotlin
│   │   └── com
│   │       └── example
│   │           └── sample_project
│   │               ├── HelloController.kt # プロジェクト作成後に追加したのはここだけ
│   │               └── SampleProjectAuthApplication.kt
│   └── resources
│       ├── application.properties
│       ├── static
│       └── templates
└── test
    └── kotlin
        └── com
            └── example
                └── sample_project
                    └── SampleProjectApplicationTests.kt

結論:SpringSecutiryのデフォルト設定によるもの

https://docs.spring.io/spring-security/reference/servlet/getting-started.html#servlet-hello-auto-configuration

Spring Boot と Spring Security のデフォルトの配置では、実行時に次の動作が実現されます。

  • あらゆるエンドポイント(Boot の/errorエンドポイントを含む)に認証されたユーザーが必要です
  • 起動時に生成されたパスワードを持つデフォルトユーザーを登録します(パスワードはコンソールに記録されます。上記の例では、パスワードは 8e557245-73e2-4286-969a-ff57fe326336 です)。
  • BCryptなどのパスワードストレージを保護します
  • フォームベースのログインおよびログアウトフローを提供する
  • フォームベースのログインとHTTP Basicを認証します
  • コンテンツネゴシエーションを提供します。Webリクエストの場合はログインページにリダイレクトし、サービスリクエストの場合は401 Unauthorized
  • CSRF攻撃を軽減
  • セッション固定攻撃を軽減
  • HTTPSを保証するためにStrict-Transport-Securityを記述する
  • スニッフィング攻撃を軽減するためにX-Content-Type-Optionsを記述する
  • 認証されたリソースを保護するキャッシュ制御ヘッダーを書き込みます
  • クリックジャッキングを軽減するためにX-Frame-Optionsを記述する
  • HttpServletRequestの認証メソッドとの統合
  • 認証の成功と失敗のイベントを公開する

依存関係に追加した時点で自動でログインページ(/login)とBasic認証が有効になる模様。
なんならエンドポイントが何もなくてもログインページは作成される。(この状態でログインしてようやくWhitelabel Error Page(404)に飛ぶ)

ログインするためのデフォルトの設定は以下

  • ユーザー名はuser
  • パスワードはコンソール上に出力されるUUID

実装コード上はどこにも存在しないし見えないので驚いた。わかっていれば便利かもだがわからなければ詰まるので、難しいと言われる理由が少しわかった。

ふじしろふじしろ

以下によるとデフォルトのユーザー名とパスワードは、application.propertiesで任意のものに設定できるとのこと。

https://docs.spring.io/spring-boot/reference/web/spring-security.html#page-title

You can change the username and password by providing a spring.security.user.name and spring.security.user.password.
訳:ユーザー名とパスワードを変更するには、spring.security.user.nameとspring.security.user.passwordを指定します。