2015-12-26 16 views

答えて

7

クライアント側のログアウトは単純ですが、所有しているトークンを破棄するだけです。サーバーサイドのログアウト機能を提供するには、アプリケーションは現在認証されているクライアント、つまり既存のトークンを認識している必要があります。トークンベースの認証での "組み込み"の問題は、トークンが公開されている場合、トークンが期限切れになるまで有効であり、「リモート無効化」ソリューションがないことです。唯一の機会は、あなたが信頼していないトークンを持つリクエストへのアクセスを避けることです。

したがって、token storeというコンテナ内のすべての公開トークンを覚えておく必要があります。

TokenStoreインターフェイスのいくつかのインプリメンテーションは、メモリ内で、または多分データベース(JdbcTokenStore)で動作するようになっています。簡単な例として、InMemoryTokenStoreで十分です。

トークンストアを使用するには、次のようにトークンストアを作成して構成する必要があります。

は、あなたのAuthorizationServerConfigurationにこれを追加します。

@Bean 
public InMemoryTokenStore tokenStore() { 
    return new InMemoryTokenStore(); 
} 

そしてAuthorizationServerEndpointsConfigurerでそれを使用します。

@Override 
public void configure(AuthorizationServerEndpointsConfigurer configurer) throws Exception { 
    configurer.authenticationManager(authenticationManager); 
    configurer.userDetailsService(userDetailsService); 
    configurer.accessTokenConverter(accessTokenConverter()); 
    configurer.tokenStore(tokenStore()); 
} 

は、あなたのResourceServerConfigurationにも、それを追加します。

@Autowired 
private InMemoryTokenStore inMemoryTokenStore; 
... 
@Override 
public void configure(ResourceServerSecurityConfigurer resources) throws Exception { 
    resources.resourceId("resource").tokenStore(inMemoryTokenStore); 
} 

ほぼすべてだこと。また、削除することに注意してください

inMemoryTokenStore.removeAccessToken(accessToken); 
inMemoryTokenStore.removeRefreshToken(refreshToken); 

:今、あなたは多分あなたが唯一のトークン(複数可)を取得する必要があり、特別なエンドポイントで、それを必要とするようなあなたのログアウト機能を実装してトークンストアからそれを削除することができますクライアントがリフレッシュトークンを使用して新しいトークンを取得することができます(アクセストークンだけが削除されている場合)。それが働いている場合はここ

は確認するために、あなたのテストに応じてテストケースである:

@Test 
public void getUserWithValidAuth() throws Exception { 
    final HttpHeaders headers = getHttpHeader(CLIENT_USER, CLIENT_SECRET); 
    final HttpEntity<String> request = new HttpEntity<>(headers); 

    final String tokenUrl = getOAuthTokenUrl(OAUTH_TOKEN_USERNAME, OAUTH_TOKEN_PASSWORD); 
    final ResponseEntity<Object> response = restTemplate.exchange(tokenUrl, HttpMethod.POST, request, Object.class); 
    assertTrue("Did not get auth tokens!", response.getStatusCode().is2xxSuccessful()); 

    final Map result = (Map) response.getBody(); 
    final String accessTokenAsString = (String) result.get(ACCESS_TOKEN); 
    final String refreshTokenAsString = (String) result.get(REFRESH_TOKEN); 

    final String resourceUrlWithToken = "http://localhost:" + port + "/users?access_token=" + accessTokenAsString; 

    final ResponseEntity<String> userResponse = restTemplate.exchange(resourceUrlWithToken, HttpMethod.GET, null, 
      String.class); 
    assertTrue("Could not request user data!", userResponse.getStatusCode().is2xxSuccessful()); 

    final OAuth2AccessToken accessToken = inMemoryTokenStore.readAccessToken(accessTokenAsString); 
    final OAuth2RefreshToken refreshToken = inMemoryTokenStore.readRefreshToken(refreshTokenAsString); 
    inMemoryTokenStore.removeAccessToken(accessToken); 
    inMemoryTokenStore.removeRefreshToken(refreshToken); 

    try { 
     restTemplate.exchange(resourceUrlWithToken, HttpMethod.GET, null, String.class); 
     fail("Should not get here, expected 401 for request with access token!"); 
    } catch (HttpClientErrorException e) { 
     // would not be needed with MockMvc 
    } 

    final String refreshTokenUrl = REFRESH_TOKEN_URL + refreshTokenAsString; 
    try { 
     restTemplate.exchange(refreshTokenUrl, HttpMethod.POST, request, Object.class); 
     fail("Should not get here, expected 401 for request with refresh token!"); 
    } catch (HttpClientErrorException e) { 
     // would not be needed with MockMvc 
    } 
} 

と、少なくともちょうど勧告、MockMvcを使用すると、簡単に、残りの通話とあなたをテストすることができます素晴らしいテストフレームワークでありますRestTemplateで作業中に障害物やボイラープレートのコードを取り除くことができます。たぶんあなたはそれを試してみたいです。

関連する問題