Spring Security OAuthを使用した主体と権限の抽出
1.概要
このチュートリアルでは、Spring BootとSpring Security OAuthを使用して、ユーザー認証をサードパーティとカスタム認証サーバーに委任するアプリケーションを作成する方法を説明します。
また、Springのhttps://docs.spring.io/spring-security-oauth2-boot/docs/current-SNAPSHOT/api/org/springframework/boot/autoconfigure/を使用して
Principal
と
Authorities
の両方を抽出する方法も示します。 security/oauth2/resource/PrincipalExtractor.html[
PrincipalExtractor
]およびhttps://docs.spring.io/spring-security-oauth2-boot/docs/current/api/org/springframework/boot/autoconfigure/security/oauth2/resource/AuthoritiesExtractor.html[
AuthoritiesExtractor
]インターフェース。
Spring Security OAuth2の紹介については、https://www.baeldung.com/spring-security-oauth[these]の記事を参照してください。
2. Mavenの依存関係
始めるには、https://search.maven.org/classic/#search%7C1%7Cg%3A%22org.springframework.security.oauth.boot%22%20AND%20a%3A%を追加する必要があります。 22spring-security-oauth2-autoconfigure%22[
spring-security-oauth2-autoconfigure
]私たちの
pom.xml
への依存関係:
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
3. Githubを使ったOAuth認証
次に、アプリケーションのセキュリティ設定を作成しましょう。
@Configuration
@EnableOAuth2Sso
public class SecurityConfig
extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http)
throws Exception {
http.antMatcher("/** ** ")
.authorizeRequests()
.antMatchers("/login** ** ")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin().disable();
}
}
つまり、誰でも
/login
エンドポイントにアクセスでき、他のすべてのエンドポイントではユーザー認証が必要になるということです。
また、設定クラスに
@ EnableOAuthSso
というアノテーションを付け、アプリケーションをOAuthクライアントに変換し、それがそのように動作するために必要なコンポーネントを作成します。
Springはデフォルトでほとんどのコンポーネントを作成していますが、それでもいくつかのプロパティを設定する必要があります。
security.oauth2.client.client-id=89a7c4facbb3434d599d
security.oauth2.client.client-secret=9b3b08e4a340bd20e866787e4645b54f73d74b6a
security.oauth2.client.access-token-uri=https://github.com/login/oauth/access__token
security.oauth2.client.user-authorization-uri=https://github.com/login/oauth/authorize
security.oauth2.client.scope=read:user,user:email
security.oauth2.resource.user-info-uri=https://api.github.com/user
ユーザーアカウント管理を扱うのではなく、第三者(この場合はGithub)に委任しているので、アプリケーションのロジックに集中することができます。
4.主体と権限の抽出
OAuthクライアントとして機能し、第三者を通じてユーザーを認証する際には、3つのステップを考慮する必要があります。
-
ユーザー認証 – ユーザーは第三者との認証を受けます
-
ユーザー認証 – 認証後、ユーザーが許可したとき
彼らに代わって特定の操作を実行するための私たちのアプリケーション。これは
scopes
お入りください
。ユーザーデータを取得する – 取得するために取得したOAuthトークンを使用します
ユーザーのデータ
ユーザーのデータを取得すると、
Springはユーザーの
Principal
および
Authorities
を自動的に作成できます。
それは受け入れられるかもしれませんが、私たちがそれらを完全に制御したいというシナリオに自分自身を見つけることが多いです。
そうするために、** Springは、デフォルトの動作を上書きするために使用できる2つのインタフェースを提供します。
-
PrincipalExtractor
– カスタムを提供するために使用できるインタフェース
Principalを抽出するロジック
**
AuthoritiesExtractor
–
PrincipalExtractor
に似ていますが、
代わりに
Authorities
抽出をカスタマイズするために使用されます
デフォルトでは、
Springは2つのコンポーネントを提供します –
FixedPrincipalExtractor
および
FixedAuthoritiesExtractor
これらのインターフェースを実装し、私たちのためにそれらを作成するための事前定義された戦略を持っている
_ –
_
。
4.1. Githubの認証をカスタマイズする
私たちの場合、Githubのユーザーデータがどのように見えるか、そして私たちが自分たちに従ってそれらを調整するために使用できるものを知っていますニーズ。
そのため、Springのデフォルトコンポーネントをオーバーライドするには、これらのインタフェースも実装する2つの
Beans
を作成するだけです。
私たちのアプリケーションの
Principal
では、単にユーザーのGithubユーザー名を使用します。
public class GithubPrincipalExtractor
implements PrincipalExtractor {
@Override
public Object extractPrincipal(Map<String, Object> map) {
return map.get("login");
}
}
ユーザーのGithubサブスクリプションに応じて(無料、それ以外の場合は)、
GITHUB
USER
SUBSCRIBED
または
GITHUB
USER
FREE
の権限を付与します。
public class GithubAuthoritiesExtractor
implements AuthoritiesExtractor {
List<GrantedAuthority> GITHUB__FREE__AUTHORITIES
= AuthorityUtils.commaSeparatedStringToAuthorityList(
"GITHUB__USER,GITHUB__USER__FREE");
List<GrantedAuthority> GITHUB__SUBSCRIBED__AUTHORITIES
= AuthorityUtils.commaSeparatedStringToAuthorityList(
"GITHUB__USER,GITHUB__USER__SUBSCRIBED");
@Override
public List<GrantedAuthority> extractAuthorities
(Map<String, Object> map) {
if (Objects.nonNull(map.get("plan"))) {
if (!((LinkedHashMap) map.get("plan"))
.get("name")
.equals("free")) {
return GITHUB__SUBSCRIBED__AUTHORITIES;
}
}
return GITHUB__FREE__AUTHORITIES;
}
}
次に、これらのクラスを使ってBeanを作成する必要もあります。
@Configuration
@EnableOAuth2Sso
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//...
@Bean
public PrincipalExtractor githubPrincipalExtractor() {
return new GithubPrincipalExtractor();
}
@Bean
public AuthoritiesExtractor githubAuthoritiesExtractor() {
return new GithubAuthoritiesExtractor();
}
}
4.2. カスタム認証サーバを使用する
サードパーティに頼るのではなく、ユーザー用に独自の承認サーバーを使用することもできます。
使用することを決定した認証サーバーにもかかわらず、
Principal
と
Authorities
の両方をカスタマイズするために必要なコンポーネントは同じままです:
PrincipalExtractor
と
AuthoritiesExtractor
。
私たちは、
user-info-uri
エンドポイントによって返されるデータを** 認識し、適切であると思うようにそれを使用するだけです。
この
記事に記載されている認証サーバーを使用してユーザーを認証するようにアプリケーションを変更しましょう。
security.oauth2.client.client-id=SampleClientId
security.oauth2.client.client-secret=secret
security.oauth2.client.access-token-uri=http://localhost:8081/auth/oauth/token
security.oauth2.client.user-authorization-uri=http://localhost:8081/auth/oauth/authorize
security.oauth2.resource.user-info-uri=http://localhost:8081/auth/user/me
認証サーバーを指定したので、両方の抽出機能を作成する必要があります。この場合、
PrincipalExtractor
は、
name
キーを使用して
Map
から
Principal
を抽出します。
public class BaeldungPrincipalExtractor
implements PrincipalExtractor {
@Override
public Object extractPrincipal(Map<String, Object> map) {
return map.get("name");
}
}
権限に関しては、私たちのAuthorization Serverはすでにそれらをその
user-info-uri
のデータに入れています。
そのため、私たちはそれらを抽出し、充実させます。
public class BaeldungAuthoritiesExtractor
implements AuthoritiesExtractor {
@Override
public List<GrantedAuthority> extractAuthorities
(Map<String, Object> map) {
return AuthorityUtils
.commaSeparatedStringToAuthorityList(asAuthorities(map));
}
private String asAuthorities(Map<String, Object> map) {
List<String> authorities = new ArrayList<>();
authorities.add("BAELDUNG__USER");
List<LinkedHashMap<String, String>> authz =
(List<LinkedHashMap<String, String>>) map.get("authorities");
for (LinkedHashMap<String, String> entry : authz) {
authorities.add(entry.get("authority"));
}
return String.join(",", authorities);
}
}
それから、Beanを
SecurityConfig
クラスに追加します。
@Configuration
@EnableOAuth2Sso
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//...
@Bean
public PrincipalExtractor baeldungPrincipalExtractor() {
return new BaeldungPrincipalExtractor();
}
@Bean
public AuthoritiesExtractor baeldungAuthoritiesExtractor() {
return new BaeldungAuthoritiesExtractor();
}
}
5.まとめ
この記事では、ユーザー認証をサードパーティとカスタム認証サーバーに委任するアプリケーションを実装し、
Principal
と
Authorities
の両方をカスタマイズする方法を示しました。
いつものように、この例の実装はhttps://github.com/eugenp/tutorials/tree/master/spring-5-security-oauth[over on Github]にあります。
ローカルで実行している場合は、アプリケーションを実行してテストできます。
localhostで:8082