2016-08-16 196 views
1

獲取在春季啓動資源服務器主要我有一個單獨的auth服務器和資源服務器 - 無論是春啓動的應用程序。我正在使用OAuth2和JWT令牌進行身份驗證和授權。從JWT令牌

我可以通過訪問auth服務器獲取令牌:

curl -X POST --user 'client:secret' -d 'grant_type=password&username=john&password=123' http://localhost:9000/auth-server/oauth/token 

和令牌附加到請求頭從資源服務器獲取資源(不同的服務器上運行)時使用它。

但是我不清楚的是,確定哪個用戶在資源服務器上登錄。

在auth服務器,我可以做這樣的事情:

@RequestMapping("/user") 
public Principal user(Principal user) { 
    return user; 
} 

與此端點將得到我的當前用戶基於使用的令牌。如果我試圖在資源服務器上做同樣的事情,我只會得到空的答覆。

我需要得到驗證用戶的ID以某種方式在資源服務器,以決定是否我應該有的數據返回給他(我有一些資源只能被其所有者訪問)。

我該怎麼做?我認爲通過使用JWT,我不需要共享相同的令牌存儲。

我可以提供代碼樣本,如果我的問題是不清楚..我只是尋找一個確認我的假設是正確的,就可以實現這種行爲 - 這是我第一次帶彈簧的安全試驗。

資源服務器鏈接到auth服務器在application.properties:

security.oauth2.resource.userInfoUri: http://localhost:9000/auth-server/user 
+0

沒有你,不管怎樣,這得到解決?我通過使用InMemoryTokenStore()而不是JwtTokenStore()來得到這個工作。不過,我想用JwtTokenStore()來達到同樣的效果。 – Yasin

+0

不幸的是沒有。我現在使用的方式是在auth服務器和資源服務器中共享相同的用戶名,並使用在Principal對象中傳遞的唯一用戶名來檢索用戶... – Smajl

回答

0

你的資源服務器不會自動奇蹟般地擺脫了身份驗證服務的主體。他們必須受到約束。將auth令牌插入標頭是正確的方法。但是,資源服務器必須「驗證」授權令牌。一旦您使用auth服務器驗證auth令牌,將返回Principal。

因此,您的資源服務器需要在您的auth服務器上調用「/ user」。

下面是一個例子。 http://technicalrex.com/2015/02/20/stateless-authentication-with-spring-security-and-jwt

+0

只有在頭部存在正確的令牌時(先前請求的表單auth服務器),資源服務器纔會返回數據。我認爲這個標記已經被驗證過了,否則它會給我401,對吧?我通過將security.oauth2.resource.userInfoUri添加到屬性來將資源服務器鏈接到auth服務器。 – Smajl

1

難道我建議另一種方式?

你需要實現自己的令牌生成,幷包裝成令牌的用戶數據。所有你需要它將必要的用戶信息放入索賠對象。然後在資源服務器上解開它。

private Map<String, Object> getClaims(UserEntity user) { 
    Map<String, Object> claims = new HashMap<>(); 
    OffsetDateTime now = OffsetDateTime.now(clock); 
    OffsetDateTime exp = now.plusMinutes(1); 

    //Standard claims 
    claims(Claims.ISSUED_AT, Date.from(now.toInstant()).getTime()); 
    claims(Claims.EXPIRATION, Date.from(exp.toInstant()).getTime()); 
    claims(Claims.ID, UUID.randomUUID()); 

    //Private claims 
    claims("user.auth", getRoles(user.getRoles())); 

    //Clear fields that should not be stored in the token 
    claims("user.data", stripUserFields(getApiUser(user))); 

    return claims; 
} 

private String buildJwtToken(Claims claims, String secretKey) throws ApplicationException { 
    DefaultJwsHeader header = new DefaultJwsHeader(); 
    if (secretKey != null) { 
     header.setAlgorithm(ALGORITHM); 
    } 
    String base64EncodedJsonHeader = Base64Util.encode(toJson("header", header), true); 
    String base64EncodedJsonBody = Base64Util.encode(toJson("body", claims), true); 
    String base64UrlEncodedBaseToken = base64EncodedJsonHeader + "." + base64EncodedJsonBody; 
    String hexDigest = createHexDigest(base64UrlEncodedBaseToken, secretKey); 
    return base64UrlEncodedBaseToken + "." + Base64Util.encode(hexDigest, true); 
} 

我們使用的是io.jsonwebtoken庫。

+1

感謝您的建議。我正試圖對此實施一些「標準」解決方案,在我看來,這是一個基本問題。我寧願以某種'春天的方式'來實現它,而不使用這些變通辦法 – Smajl