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;
        }

    }
}

问题是:

我可以通过“authorization_code”从 spring zuul ui-server 登录,并且可以访问 ResourceServer 数据。

但是当 access_token 过期(120s)时,在重新获取 ResourceServer 数据时,我看到 mongoTokenStore 删除了现有的 access_token ,但为什么不自动刷新新的 access_token

如何解决?

4

1 回答 1

0

刷新令牌的重点是为 OAuth2 添加一个安全维度。

当最终用户获得访问令牌时,他现在可以访问令牌授予他的授权规则内的任何资源。

如果他的访问令牌以某种方式被盗,攻击者现在可以访问访问令牌授权他的任何资源,但是如果我们为访问令牌设置到期时间,攻击者将有有限的访问时间。

话虽如此,如果 spring oauth2 会自动刷新该令牌,则不会应用更多的安全方面,并且刷新令牌的整个想法将被浪费。

因此,总而言之,确保您的最终用户再次通过 OAuth2 重新授权是您的责任。

您还可以阅读以下内容:

为什么 OAuth v2 既有访问令牌又有刷新令牌?

于 2016-11-27T18:17:45.283 回答