2017-11-02 2 views
2

Keycloakサーバーをセットアップしました。レルムとクライアントなどを設定しました。 "org.keycloak:keycloak-spring-boot-starter"でSpringブートサービスを作成し、RestControllerを保護しました。魅力のように動作します。Spring Security RemoteTokenServiceをKeycloakで使用する方法

しかし、私がSpring Securityを使用しようとすると(キークロークの特定の依存関係なしで)、私は立ち往生しています。ここ

は私のGradleです:

dependencies { 
compile('org.springframework.boot:spring-boot-starter-security') 
compile('org.springframework.security.oauth:spring-security-oauth2') 

compile('org.springframework.boot:spring-boot-starter-web') 
compileOnly('org.projectlombok:lombok') 
testCompile('org.springframework.boot:spring-boot-starter-test') 
testCompile('org.springframework.security:spring-security-test') 

}

これは私のSecurityConfigです:

@Configuration 
@EnableResourceServer 
public class ResourceServerConfiguration extends 
ResourceServerConfigurerAdapter { 

@Override 
public void configure(HttpSecurity http) throws Exception { 
    http.authorizeRequests() 
     .antMatchers("/person/**").hasRole("DEMO_SPRING_SECURITY") 
     .anyRequest().authenticated() 
     .and().formLogin().disable(); 
} 

@Override 
public void configure(ResourceServerSecurityConfigurer resources) throws Exception { 

    resources.resourceId("demo-client"); 
    RemoteTokenServices tokenServices = new RemoteTokenServices(); 
    tokenServices.setCheckTokenEndpointUrl(
     "http://localhost:8280/auth/realms/demo-realm/protocol/openid-connect/token/introspect"); 
    tokenServices.setClientId("demo-client"); 
    tokenServices.setClientSecret("80e19056-7770-4a4a-a3c4-06d8ac8792ef"); 
    resources.tokenServices(tokenServices); 
} 
} 

今、私がアクセスサーバー試してみてください。

  1. をアクセスを取得しますトークン(RESTクライアント経由) デコードJWTは、次のようになります。
{ 
"jti": "78c00562-d80a-4f5a-ab08-61ed10cb575c", 
"exp": 1509603570, 
"nbf": 0, 
"iat": 1509603270, 
"iss": "http://localhost:8280/auth/realms/demo-realm", 
"aud": "demo-client", 
"sub": "6ee90ba4-2854-49c1-9776-9aa95b6ae598", 
"typ": "Bearer", 
"azp": "demo-client", 
"auth_time": 0, 
"session_state": "68ce12fb-3b3f-429d-9390-0662f0503bbb", 
"acr": "1", 
"client_session": "ec0113e1-022a-482a-a26b-e5701e5edec1", 
"allowed-origins": [], 
"realm_access": { 
    "roles": [ 
    "demo_user_role", 
    "uma_authorization" 
    ] 
}, 
"resource_access": { 
    "account": { 
    "roles": [ 
     "manage-account", 
     "manage-account-links", 
     "view-profile" 
    ] 
    } 
}, 
"name": "Jim Panse", 
"preferred_username": "demo-user", 
"given_name": "Jim", 
"family_name": "Panse", 
"email": "[email protected]" 
} 

しかし、私はAccessDeniedExceptionを取得します。

2017-11-02 07:18:05.344 DEBUG 17637 --- [nio-8080-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: 

or[email protected]1f3ee7e1: 校長:デモ、クライアント。資格:[プロテクト];認証済み:真; 詳細:remoteAddress = 127.0.0.1、tokenType = BearertokenValue =; 権限を与えられていません2017-11-02 07:18:05.348 DEBUG 17637 --- [nio-8080-exec-1] ossaccess.vote.AffirmativeBased:投票者: org.springframework.security.web.access。 [nio-8080-exec-1] osswaExceptionTranslationFilter:アクセスが拒否されました(ユーザーは 匿名ではありません)。 AccessDeniedHandler

に委任org.springframework.security.access.AccessDeniedException:アクセスが

を拒否され、私はRemoteTokenServiceをdebugedとKeycloakはまったく同じaccesstokenで応答がわかりました。どちらが良いですか。 DefaultAccessTokenConverterは存在しないフィールドauthoritiesからユーザーロールを読み取ろうとしています。 OAuth2WebSecurityExpressionHandlerは、ユーザーには何の役割もないと評価します。 - >アクセスが

を拒否だから私の質問:

は春のセキュリティはKeycloakアクセストークンを動作させるためにneccessaryは何ですか?

答えて

3

keycloak管理コンソールから、あなたのクライアント「のデモ・クライアント」の請求名称「当局」とタイプユーザーレルム役割のトークンマッパーを作成することができます。 このアクセストークンにはこの属性のロール名が含まれており、カスタムはありませんDefaultAccessTokenConverterが必要です。

+0

あなたは正しいです。驚くばかり。もし私が以前にそれを知っていたら: - D – HaVonTe

1

ここでこの問題を定式化した直後に、自分で解決策を見つけました。場合によっては、問題を表現しようとするのが役に立ちます。

解決策は、DefaultAccessTokenConverterをオーバーライドして、「realm_access」フィールドの読み方を教えることです。その醜いが、それは動作します:

@Override 
public void configure(ResourceServerSecurityConfigurer resources) throws Exception { 

    resources.resourceId("demo-client"); 
    RemoteTokenServices tokenServices = new RemoteTokenServices(); 
    tokenServices.setCheckTokenEndpointUrl(
     "http://localhost:8280/auth/realms/demo-realm/protocol/openid-connect/token/introspect"); 
    tokenServices.setClientId("demo-client"); 
    tokenServices.setClientSecret("80e19056-7770-4a4a-a3c4-06d8ac8792ef"); 
    tokenServices.setAccessTokenConverter(new KeycloakAccessTokenConverter()); 
    resources.tokenServices(tokenServices); 

} 
private class KeycloakAccessTokenConverter extends DefaultAccessTokenConverter { 

    @Override 
    public OAuth2Authentication extractAuthentication(Map<String, ?> map) { 
     OAuth2Authentication oAuth2Authentication = super.extractAuthentication(map); 
     Collection<GrantedAuthority> authorities = (Collection<GrantedAuthority>) oAuth2Authentication.getOAuth2Request().getAuthorities(); 
     if (map.containsKey("realm_access")) { 
      Map<String, Object> realm_access = (Map<String, Object>) map.get("realm_access"); 
      if(realm_access.containsKey("roles")) { 
       ((Collection<String>) realm_access.get("roles")).forEach(r -> authorities.add(new SimpleGrantedAuthority(r))); 
      } 
     } 
     return new OAuth2Authentication(oAuth2Authentication.getOAuth2Request(),oAuth2Authentication.getUserAuthentication()); 
    } 
} 
関連する問題