2016-08-16 7 views
1

私は、別々の認証サーバとリソースサーバを持っています。どちらもSpringブートアプリケーションです。私は認証と承認のためにJWTトークンでOAuth2を使用しています。JWTトークンからSpringブートリソースサーバのプリンシパルを取得

私は、認証サーバにアクセスしてトークンを取得することができます:

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

とリソースサーバ(別のサーバー上で実行されている)からリソースを取得するときに、要求ヘッダーにトークンを取り付けることによって、それを使用しています。

私には不明な点は、どのユーザーがリソースサーバーにログインしているかを判断することです。認証サーバで

は、私はこのような何かを行うことができます:

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

と、このエンドポイントが使用されるトークンに基づいて、私に現在のユーザーを取得します。しかし、リソースサーバーで同じことをしようとすると、空の応答しか得られません。

リソースサーバーに何らかの形で認証されたユーザーのIDを取得して、データを返す必要があるかどうかを判断する必要があります(所有者のみがアクセスできるリソースがあります)。

どうすればいいですか?私はJWTを使うことで、同じトークンストアを共有する必要はないと思っていました。

私の質問がはっきりしない場合は、私はコードサンプルを提供することができます。私は私の前提が正しいことを確認しており、この動作を達成することができます - これは私の初めてのスプリングセキュリティを試しています。

リソースサーバは、application.propertiesに認証サーバにリンクされている:

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

あなたは、万一、これを解決しましたか?私はJwtTokenStore()の代わりにInMemoryTokenStore()を使用してこれを動作させました。それでも、私はJwtTokenStore()を使って同じことを達成したいと思います。 – Yasin

+0

残念ながらいいえ。私が今使用している方法は、認証サーバーとリソースサーバーで同じユーザー名を共有し、プリンシパルオブジェクトで渡されるこの一意のユーザー名を使用してユーザーを取得することです。 – Smajl

答えて

0

あなたのリソースサーバーが自動魔法の認証サービスから元本を取得することはありません。彼らは縛られなければならない。 authトークンをヘッダーに挿入するのが正しい方法です。ただし、リソースサーバーは認証トークンを「検証」する必要があります。認証サーバーで認証トークンを検証すると、プリンシパルが返されます。

したがって、リソースサーバーは認証サーバーで「/ user」を呼び出す必要があります。

ここは例です。 http://technicalrex.com/2015/02/20/stateless-authentication-with-spring-security-and-jwt

+0

正しいトークンがヘッダー(以前に要求されたフォーム認証サーバー)に存在する場合のみ、リソースサーバーがデータを返すようになった。私はトークンがすでに検証されていると仮定しました。それ以外の場合、それは私に401を与えますか?プロパティーにsecurity.oauth2.resource.userInfoUriを追加して、リソースサーバーを認証サーバーにリンクしました。 – 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

関連する問題