0

mongo カスタム tokenStore と codeService を使用します。

これは私のカスタム mongoTokenStore です。

public class MongoTokenStore implements TokenStore {

    private final MongoAccessTokenRepository mongoAccessTokenRepository;
    private final MongoRefreshTokenRepository mongoRefreshTokenRepository;
    private AuthenticationKeyGenerator authenticationKeyGenerator =
            new DefaultAuthenticationKeyGenerator();

    public MongoTokenStore(MongoAccessTokenRepository mongoAccessTokenRepository, MongoRefreshTokenRepository mongoRefreshTokenRepository) {
        this.mongoAccessTokenRepository = mongoAccessTokenRepository;
        this.mongoRefreshTokenRepository = mongoRefreshTokenRepository;
    }


    @Override
    public OAuth2Authentication readAuthentication(OAuth2AccessToken oAuth2AccessToken) {
        return readAuthentication(oAuth2AccessToken.getValue());
    }

    @Override
    public OAuth2Authentication readAuthentication(String tokenId) {
        return mongoAccessTokenRepository.findByTokenId(tokenId)
                .map(MongoAccessToken::getAuthentication)
                .orElse(null);
    }

    @Override
    public void storeAccessToken(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {

        MongoAccessToken mongoAccessToken = new MongoAccessToken(oAuth2AccessToken, oAuth2Authentication,
                authenticationKeyGenerator.extractKey(oAuth2Authentication));
        mongoAccessTokenRepository.save(mongoAccessToken);
    }

    @Override
    public OAuth2AccessToken readAccessToken(String tokenValue) {
        return mongoAccessTokenRepository.findByTokenId(tokenValue)
                .map(MongoAccessToken::getOAuth2AccessToken)
                .orElse(null);
    }

    @Override
    public void removeAccessToken(OAuth2AccessToken oAuth2AccessToken) {
        mongoAccessTokenRepository.findByTokenId(oAuth2AccessToken.getValue())
                .ifPresent(mongoAccessTokenRepository::delete);
    }

    @Override
    public void storeRefreshToken(OAuth2RefreshToken oAuth2RefreshToken, OAuth2Authentication oAuth2Authentication) {
        MongoRefreshToken token=new MongoRefreshToken(oAuth2RefreshToken,oAuth2Authentication);
        mongoRefreshTokenRepository.save(token);

    }

    @Override
    public OAuth2RefreshToken readRefreshToken(String tokenValue) {
        return mongoRefreshTokenRepository.findByTokenId(tokenValue)
                .map(MongoRefreshToken::getOAuth2RefreshToken)
                .orElse(null);
    }

    @Override
    public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken oAuth2RefreshToken) {

        return mongoRefreshTokenRepository.findByTokenId(oAuth2RefreshToken.getValue())
                .map(MongoRefreshToken::getAuthentication)
                .orElse(null);
    }

    @Override
    public void removeRefreshToken(OAuth2RefreshToken oAuth2RefreshToken) {
        mongoRefreshTokenRepository.findByTokenId(oAuth2RefreshToken.getValue())
                .ifPresent(mongoRefreshTokenRepository::delete);
    }

    @Override
    public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken oAuth2RefreshToken) {

        mongoAccessTokenRepository.findByRefreshToken(oAuth2RefreshToken.getValue())
                .ifPresent(mongoAccessTokenRepository::delete);
    }

    @Override
    public OAuth2AccessToken getAccessToken(OAuth2Authentication oAuth2Authentication) {

        return mongoAccessTokenRepository.findByAuthenticationId(authenticationKeyGenerator
                .extractKey(oAuth2Authentication))
                .map(MongoAccessToken::getOAuth2AccessToken)
                .orElse(null);
    }

    @Override
    public Collection<OAuth2AccessToken> findTokensByClientIdAndUserName(String s, String s1) {

        return mongoAccessTokenRepository.findByClientIdAndUserName(s,s1)
                .stream()
                .map(MongoAccessToken::getOAuth2AccessToken)
                .collect(Collectors.toList());
    }

    @Override
    public Collection<OAuth2AccessToken> findTokensByClientId(String s) {
        return mongoAccessTokenRepository.findByClientId(s)
                .stream()
                .map(MongoAccessToken::getOAuth2AccessToken)
                .collect(Collectors.toList());
    }
}

これは私のカスタム mongoCodeService です。

@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MongoAuthenticationCodeService extends RandomValueAuthorizationCodeServices{

    private final MongoAuthenticationCodeRepository repository;

    @Override
    protected void store(String code, OAuth2Authentication oAuth2Authentication) {

        repository.save(new MongoAuthenticationCode(code,oAuth2Authentication));
    }

    @Override
    protected OAuth2Authentication remove(String code) {

        return repository.findOneByCode(code)
                .map(MongoAuthenticationCode::getAuthentication)
                .orElse(null);
    }
}

と私の OAuth2Config:

@Configuration
public class OAuth2ServerConfiguration {

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends
            ResourceServerConfigurerAdapter {

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) {
            resources.resourceId(READ_AND_WRITE_RESOURCE_ID);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/webjars/**", "/oauth/authorize/**", "/", "/customLogout",
                            "/oauth/check_token/**", "/login").permitAll()
                    .mvcMatchers(HttpMethod.GET, "/loginAttemptUsers").hasRole("ADMIN")
                    .anyRequest().authenticated();
        }

    }

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends
            AuthorizationServerConfigurerAdapter {

        @Autowired
        @Qualifier("authenticationManagerBean")
        private AuthenticationManager authenticationManager;


        @Autowired
        private CustomUserDetailService customUserDetailService;

        @Autowired
        private MongoAuthenticationCodeService mongoAuthenticationCodeService;

        @Autowired
        private MongoTokenStore mongoTokenStore;

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints)
                throws Exception {

            endpoints
                    .authorizationCodeServices(mongoAuthenticationCodeService)
                    .tokenStore(mongoTokenStore)
                    .authenticationManager(authenticationManager)
                    .userDetailsService(customUserDetailService)
                    .approvalStoreDisabled();

        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

            clients
                    .inMemory()
                    .withClient("kksdi2388wmkwe")
                    .authorizedGrantTypes("authorization_code", "password", "refresh_token")
                    .scopes("read", "write")
                    .resourceIds("ReadAndWriteResource")
                    .secret("kksd23isdmsisdi2")
                    .autoApprove(true)
                    .accessTokenValiditySeconds(120)
                    .refreshTokenValiditySeconds(1200);

        }

        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
            oauthServer
                    .tokenKeyAccess("permitAll()")
                    .checkTokenAccess("isAuthenticated()");
        }

        @Bean
        @Primary
        public DefaultTokenServices tokenServices() {
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            tokenServices.setSupportRefreshToken(true);
            tokenServices.setTokenStore(tokenStore);
            return tokenServices;
        }

    }
}

問題は:

spring zuul ui-server から「authorization_code」でログインでき、ResourceServer データにアクセスできます。

しかし、access_token の有効期限が切れたとき (120 秒)、ResourceServer データを再取得しているときに、mongoTokenStore が既存の access_token を削除したことがわかりますが、新しい access_token を自動的に更新しないのはなぜですか?

それを解決する方法は?

4

1 に答える 1

0

リフレッシュ トークンの要点は、OAuth2 にもう 1 つのセキュリティ ディメンションを追加することです。

エンド ユーザーがアクセス トークンを取得すると、トークンが付与する承認規則内の任意のリソースにアクセスできるようになります。

アクセス トークンが何らかの形で盗まれた場合、攻撃者はアクセス トークンが許可する任意のリソースにアクセスできるようになりますが、アクセス トークンに有効期限を設定すると、攻撃者のアクセス時間は制限されます。

そうは言っても、Spring oauth2 がそのトークンを自動的に更新すると、もう 1 つのセキュリティ面が適用されず、トークンを更新するというアイデア全体が無駄になります。

したがって、エンド ユーザーが OAuth2 経由で再度認証されるようにするのは、あなたの責任です。

これも読むことができます:

OAuth v2 にアクセス トークンと更新トークンの両方があるのはなぜですか?

于 2016-11-27T18:17:45.283 に答える