Spring Security で、アクセスト�`クンを�編^するリソ�`スサ�`バ�`を�g廾する
峻さん、こんにちは。室宝蝕�kグル�`プの稼-看噛温敬温稼です。
かつてエミュ�`との�蚯�に移れ、150定參貧�U狛した書でもウサギと�蚯�をしているオ�`ストラリア屓軒ですが、2015定には竪を盃待議な伏麗として傚�蕾叱罎靴討い泙后�オ�`ストラリアへ唾佩に佩った縞は、ウサギや竪を需かけても芦叟に除篠らない圭が措いかもしれません。
云籾です。
Spring Security でクライアントから鞭け函ったアクセスト�`クンを�編^して、勣李のリソ�`スを卦抜するリソ�`スサ�`バ�`を�g廾することが竃栖ます。書指はSpring Securityでアクセスト�`クンを�編^するやり圭をお��しします。
朕肝
Spring Security でアクセスト�`クンの�編^
ゴ�`ル
Spring Security でリソ�`スサ�`バ�`�箸��g廾します。リソ�`スサ�`バ�`ではクライアントから鞭け函ったアクセスト�`クンを�編^します。なお、IdPにはKeycloakを旋喘しています。

アクセスト�`クンの�編^に駅勣なプロパティを協吶する
アクセスト�`クンの�編^に駅勣なプロパティをapplication.propertiesに協吶します。
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/realms/myrealm或鴛禽遺範�^の扮とは離って、アクセスト�`クンの�編^に駅勣なプロパティは1つです。アクセスト�`クンの�k佩宀の雨檎鴛を協吶します。ここで協吶した�k佩宀が�k佩したアクセスト�`クンのみを鞭け原けるようになります。
アクセスト�`クンを�編^する皆艶界顎姻庄岳霞酷庄鉛岳艶姻遺鞄温庄稼を伏撹する
アクセスト�`クンを�編^する恷弌のコ�`ドは參和となります。
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// アクセスト�`クン�編^
http
.authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated())
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
return http.build();
}
}http.authorizeHttpRequests(...)は、クライアントがアクセスしたパスに��して、クライアントが癖俳な�慙泙鰉个靴討い襪�チェックするためのメソッドです。この魁栽は、すべてのパスにアクセスする縞は、アクセスト�`クンの�編^が或悪である駅勣があります。
http.oauth2ResourceServer(...)は、アクセスト�`クンを�編^するためのメソッドです。Spring Securityが��鬉靴討い襯肌`クンはJWTと、Opaque ト�`クンの2つになります。Opaque ト�`クン とは、そのト�`クンをキ�`として�J辛サ�`バ�`へ��い栽わせることで�編^するト�`クンです。Opaque ト�`クン徭悶は採の秤�鵑魍屬燭此△修琳佗蹐和卻�であることが謹いです。keycloakのアクセスト�`クンはJWT侘塀ですので、貧��のコ�`ドはJWTを�編^するように�g廾しています。
貧芝のコ�`ドにより、デジタル俸兆の�編^に紗えて、參和の�編^を佩います。
- 庄壊壊顎艶姻のチェック
�覿┐靴討い覆ぐk佩宀が�k佩したアクセスト�`クンは鰻赫とします。 - 嗤�親斛泙離船Д奪�
嗤�親斛泙�俳れたアクセスト�`クンを鰻赫とします。
アクセスト�`クンのカスタム�編^を弖紗する
蒙に弖紗の�編^が涙ければ、參貧のコ�`ドで噴蛍です。しかし、嶄には弖紗でアクセスト�`クンを�編^したいこともあるかと房います。一艶霞界鉛看温一が�k佩するアクセスト�`クンには、そのユ�`ザ�`に嚥えられたロ�`ルが鯉追されています。書指はこのロ�`ルを需て、蒙協のロ�`ル參翌の魁栽は詳倦するようにしてみましょう。
まずは皆艶界顎姻庄岳霞酷庄鉛岳艶姻遺鞄温庄稼の伏撹のところを俐屎します。
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// アクセスト�`クン�編^
http
.authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated())
.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.decoder(this.jwtDecoder())));
return http.build();
}oauth2.jwt(...)のところで、徭念のJWT Decoderを�O協してあげるようにしています。メソッドthis.jwtDecoder()の嶄附は參和の宥りです。
// メンバ�篳�
@Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
private String issuerUri;
// JwtDecoderを伏撹して卦抜する
private JwtDecoder jwtDecoder() {
// デフォルトのJWT Decoderを伏撹
NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder) JwtDecoders.fromIssuerLocation(issuerUri);
// アクセスト�`クンのカスタム�編^
OAuth2TokenValidator<Jwt> validators = new DelegatingOAuth2TokenValidator<>(
JwtValidators.createDefaultWithIssuer(issuerUri), // 庄壊壊顎艶姻のチェック、嗤�親斛泙離船Д奪�
roleValidator() // ロ�`ルのチェック
);
jwtDecoder.setJwtValidator(validators);
return jwtDecoder;
}
メソッドの匯佩朕では、デフォルトのJWT Decoderを伏撹しています。哈方には�k佩宀のURIが駅勣になりますので、application.propertiesに協吶したissuer-uriを峺協してあげます。
jwtDecoder.setJwtValidator(...)でアクセスト�`クンの�編^�I尖を峺協することが竃栖ます。峺協する�編^�I尖には、云栖デフォルトでチェックする仝庄壊壊顎艶姻のチェック々と仝嗤�親斛泙離船Д奪�々に紗えて、書指弖紗するチェック�I尖をまとめて峺協する駅勣があります。
roleValidator()の嶄附は參和の宥りです。
@SuppressWarnings("unchecked")
private OAuth2TokenValidator<Jwt> roleValidator() {
return jwt -> {
Map<String, Object> resourceAccess = jwt.getClaim("resource_access");
Map<String, Object> clientts = (Map<String, Object>) resourceAccess.get(jwt.getClaim("azp"));
List<String> roles = (List<String>) clientts.get("roles");
if (roles.contains("admin")) {
return OAuth2TokenValidatorResult.success();
} else {
OAuth2Error error = new OAuth2Error("unauthorized", "", null);
return OAuth2TokenValidatorResult.failure(error);
}
};
}干敬岳を鞭け函るので、その嶄附を需て、温糸馨庄稼ロ�`ルが原嚥されていれば或悪、原嚥されていなければ鰻赫としています。チェック或悪とする魁栽はOAuth2TokenValidatorResult.success()を卦抜します。チェック鰻赫の魁栽はOAuth2TokenValidatorResult.failure(error)を卦抜します。
參貧の�g廾により徭念の�編^�I尖を弖紗することが竃栖ます。adminロ�`ルを原嚥されていないユ�`ザ�`がリソ�`スサ�`バ�`へアクセスしてきた�Hは、403 Access Denied が卦抜されるようになります。
おわりに
リソ�`スサ�`バ�`迦はアクセスト�`クンの�編^ぐらいしかやることないので、或鴛禽遺範�^を佩うクライアント迦と曳べると酒殆でいいですね。
書指は徭念でアクセスト�`クンの�編^�I尖を弖紗してみました。その匯箭としてロ�`ルによるアクセス崙囮を佩っていますが、云栖であればロ�`ルによるアクセス崙囮はhttp.authorizeHttpRequests(...)でやった圭が措いです。http.authorizeHttpRequests(...)を聞ったアクセス崙囮は肝指やりたいと房います。
ではまた。
