6

リソース所有者の資格情報許可タイプを使用しています ( oauth2:passwordinを使用していますsecurity-config.xml。このシナリオを実行して、私の苦境を説明しましょう。

  1. ボブは権限を持って作成されましたROLE_USER
  2. Bob が oauth2 で保護されたリソースにアクセスしようとする
  3. Bob は公式のモバイル アプリを使用してアクセスしているため、クライアントの資格情報は正しいです。
  4. Bob のアクセス トークンが作成され、 に保存され、彼の、、およびTokenStoreにキーが付けられます。( DefaultAuthenticationKeyGenerator.javaを参照)usernameclient_idscope
  5. Bob の電話は、このアクセス トークンを使用して保護されたサービスを呼び出そうとしますが、それらのサービスにはユーザーが の を持っている必要がありauthorityますROLE_MOBILE_USER
  6. Bob はデータベースの所有者に連絡ROLE_MOBLE_USERし、データベースに自分のユーザーを追加しました。
  7. Bob は別のアクセス トークンを取得しようとしますが、DefaultTokenServices動作していない同じアクセス トークンが返されます。
  8. 彼の新しいアクセス トークンを利用する唯一の方法authorityは、古いアクセス トークンの有効期限が切れるまで待って、正しいauthority.

これに対処する方法はいくつかあります。

ROLE_MOBILE_USERたとえば、 Bob の権限に追加する管理アプリは、データベース内のすべてのアクセス トークンと承認をクリアできます。このようにしDefaultTokenServicesて、新しい OAuth2Authentication としてシリアル化された正しい権限を持つ新しい権限が作成されます。ただし、この時点では (少なくともまだ) 管理 Web アプリケーションを OAuth に関与させたくない場合があります。可能であれば、管理アプリの問題をできるだけ簡潔にしたいと考えています。現在、oauth への依存関係はありません。

DELETEメソッドをエンドポイントに公開し、保存されたトークンが古くなっている/oauth/access_token場合に備えて、そのアクセス トークンを削除して再要求するようモバイル アプリに指示することができます。authoritiesただし、これは回避策のように感じます。

最後にauthorities、自分で定義したをシリアル化できAuthenticationKeyGeneratorます。基本的に、認証のusernameclient_idscope、およびauthoritiesを使用し、それらに対して同じダイジェスト アルゴリズムを実行します。このようにして、Bob がログインしようとすると、同じアクセス トークンを取得しますが、基礎となるトークン ストアは、(トークン グランター Bean の認証マネージャーからの) 別の認証を持っていることを認識し、そのデータベースを更新します。このソリューションで私が抱えている問題は、基盤となるトークン ストアの実装動作に単純に依存していることです (ただし、 と の両方InMemoryTokenStoreJdbcTokenStoreこのように動作します)。

より良い/よりクリーンなソリューションを考えられますか? 私はこれを考えすぎていますか?

前もって感謝します。

4

3 に答える 3

2

認証情報が送信されるときに特定のユーザーのすべてのトークンを削除することで、アプリでこの問題を解決しました。

カスタム AuthenticationProvider Bean を使用します。

@Component("authenticationProvider")
public class AuthenticationProviderImpl implements AuthenticationProvider

トークン ストア Bean のオートワイヤー。

@Autowired
@Qualifier("tokenStore")
private TokenStore tokenStore;

次に、authenticate メソッドで、資格情報が 2 回目に渡された場合に、特定のユーザーのすべてのトークンを削除します。

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;

    try {
         //Do authentication

        //Delete previous tokens
        Collection<OAuth2AccessToken> tokenCollection = tokenStore.findTokensByUserName(token.getName());
        for (OAuth2AccessToken oToken : tokenCollection){
            tokenStore.removeAccessToken(oToken);
        }

        //return Authentication;
    }
}

ほとんどの要求はトークンを使用し、これを完全にバイパスしますが、資格情報が渡されると、新しいトークンが生成されます。このトークンは、すべての新しいロールとユーザーに加えられた変更を含む新しい認証オブジェクトに関連付けられます。

于 2013-10-18T03:30:02.047 に答える