やりたいこと
Spring Boot 1.5.15環境でOAuth2.0によるシングルサインオン(SSO)を実現したい.
認可サーバとしてGitHub OAuthを利用したい.
環境
Spring Boot 1.5.15 + JDK 1.8 + Maven
利用した技術について
Spring Security Web
https://spring.io/projects/spring-security
クライアントとWebアプリケーションの間のSecurity Filter Chainを提供する.
各Filterでは認証されていないユーザのアクセス拒否などのフィルタリングが可能.
Security Filter ChainはFilter Chain Proxyで管理する.
Spring Securityの設定はWebSecurityConfigurerAdapterというデフォルト設定クラスを継承し,必要なものをオーバーライドする.
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration // 設定クラスを自動的に読み込む
@EnableWebSecurity // Spring Securityを有効化
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(WebSecurity web) throws Exception {
// WebSecurityのメソッドチェーンでFilter Chain Proxyの設定(≒全体的な設定)を記述
...
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// HttpSecurityのメソッドチェーンでFilter Chainの設定(≒細かい設定)を記述
...
}
}
Thymeleafでユーザ情報を利用するにはthymeleaf-extras-springsecurityを利用する.
https://github.com/thymeleaf/thymeleaf-extras-springsecurity
OAuth2.0
https://tools.ietf.org/html/rfc6749
https://openid-foundation-japan.github.io/rfc6749.ja.html
認可(Authorization, AuthZ)のためのフレームワーク.
OAuth2.0の登場人物はユーザ,認可サーバ,リソースサーバ,クライアントの4つ.
ユーザは認可サーバを通じて,リソースサーバにあるリソースの使用をクライアントに認可する.
以下の記事が非常にわかりやすくまとめている.
https://qiita.com/busyoumono99/items/1092fdc64d5a64d021d5
OAuth2.0によるSSO
OAuth2.0において,リソースサーバからユーザ情報を取得して照合することで認証(Authentication, AuthN)が実現できる.
GitHub OAuthによるSSOの場合は
- ユーザ = 人
- 認可サーバ = GitHub
- リソースサーバ = GitHub
- クライアント = Webアプリケーション
となる.
Spring Securityで利用するにはSpring Security OAuthを利用する.
application.properties
のsecurity.oauth2.resource.*
にリソースの設定を,security.oauth2.client.*
にクライアントの設定を記述する.
https://spring.io/projects/spring-security-oauth
実装
リソースURIは/demo
.
<dependencies>
<!-- Web application -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- OAuth2.0 SSO -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class DemoController {
@GetMapping("/")
public String home() {
return "home";
}
}
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="utf-8"/>
<title>Home</title>
</head>
<body>
<h1>Hello, <span sec:authentication="name"></span></h1>
</body>
</html>
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
@EnableOAuth2Sso
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated(); // 全てのURIへのアクセスにログインが必要
}
}
# 改行までが値と見なされることに注意
server.port=8080
server.context-path=/demo
# OAuth2クライアント(本アプリケーション)の設定
# クライアントクレデンシャル
security.oauth2.client.client-id=${DEMO__GITHUB_OAUTH_CLIENT_ID}
security.oauth2.client.client-secret=${DEMO__GITHUB_OAUTH_CLIENT_SECRET}
# アクセストークン取得URI
security.oauth2.client.access-token-uri=https://github.com/login/oauth/access_token
# 認可URI
security.oauth2.client.user-authorization-uri=https://github.com/login/oauth/authorize
# 認証スキーマ
security.oauth2.client.client-authentication-scheme=form
# OAuth2リソースサーバ(GitHub)の設定
# ユーザ情報取得URI
security.oauth2.resource.user-info-uri=https://api.github.com/user
# アクセストークンではなくリソースからユーザ情報を取得
security.oauth2.resource.prefer-token-info=false
# OAuth2によるSSOの設定
# SSOログインURI(非認証時のリダイレクトURI)
security.oauth2.sso.login-path=/login
ハマったこと
- application.propertiesでは行頭が
#
または!
のときコメント行と見なされる.key=value # comment
のように値に続けてコメントを書くことはできない. - spring-security-oauth2-autoconfigureはSpring Boot 1系では使えない.