2015-09-08 29 views
2

實現Spring OAuth2安全性,並在使用同一用戶登錄時獲得相同的訪問令牌,但從不同的設備登錄。當我從這些設備中的任何一個註銷時(撤銷令牌),其他設備也將被註銷。這是預期的行爲還是我錯過了什麼?希望分享大量的代碼不會有太大的幫助,所以這個問題簡單而簡單。實現Spring OAuth2,從不同設備獲取相同的訪問令牌

回答

2

的DefaultTokenServices的默認行爲是(基於現有TokenStore實現的行爲)

http://forum.spring.io/forum/spring-projects/security/oauth/121797-multiple-valid-oauth-access-tokens-for-same-client

如果你想每一個設備被賦予不同的現有令牌再利用access_token然後創建你自己的AuthenticationKeyGenerator eg在授權過程中發送您的設備ID,並讓您的設備ID處理該設備的access_token

+0

嗨MangEngkus,感謝您的回答,我會嘗試這種方法,讓你知道 – Soumyaansh

+0

感謝您MangEngkus解決方案爲我 – Soumyaansh

2

(請閱讀org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator碼放在以下解決方案的來龍去脈)

DefaultAuthenticationKeyGenerator在春天有售。我剛剛創建了一個具有一個擴展名的相同代碼的自定義版本,即從客戶端發送的device_id,因爲如下從OAuth2Authentication檢索請求參數;

String deviceId = authentication.getOAuth2Request().getRequestParameters().get("device_id")

,然後放入values圖(用於最後生成的令牌)。因此,device_id成爲token的一部分,從而導致每個設備具有唯一的令牌。

以下是完整的解決方案,其中大部分是DefaultAuthenticationKeyGenerator除了上面解釋的位。

public class CustomAuthenticationKeyGenerator implements AuthenticationKeyGenerator 
{ 
    private static final String CLIENT_ID = "client_id"; 

    private static final String SCOPE = "scope"; 

    private static final String USERNAME = "username"; 

    @Override 
    public String extractKey(OAuth2Authentication authentication) { 
     Map<String, String> values = new LinkedHashMap<String, String>(); 
     OAuth2Request authorizationRequest = authentication.getOAuth2Request(); 
     if (!authentication.isClientOnly()) { 
      values.put(USERNAME, authentication.getName()); 
     } 
     values.put(CLIENT_ID, authorizationRequest.getClientId()); 
     if (authorizationRequest.getScope() != null) { 
      values.put(SCOPE, OAuth2Utils.formatParameterList(authorizationRequest.getScope())); 
     } 

     String deviceId = authorizationRequest.getRequestParameters().get(CustomHeader.device_id.name()); 
     if(deviceId != null && !deviceId.isEmpty()) { 
      values.put("device_id", deviceId); 
     } 

     MessageDigest digest; 
     try { 
      digest = MessageDigest.getInstance("MD5"); 
     } 
     catch (NoSuchAlgorithmException e) { 
      throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK)."); 
     } 

     try { 
      byte[] bytes = digest.digest(values.toString().getBytes("UTF-8")); 
      return String.format("%032x", new BigInteger(1, bytes)); 
     } 
     catch (UnsupportedEncodingException e) { 
      throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK)."); 
     } 
    } 
}