【问题标题】:Spring boot Security, Oauth2 replace access token with long-lived token from facebookSpring Boot Security,Oauth2 用来自 facebook 的长寿命令牌替换访问令牌
【发布时间】:2019-07-14 22:25:53
【问题描述】:

我一直在关注Dave Syer astounding tutorial 在为移动设备(Android 和 iOS)提供 RESTful API 的微服务中实现 OAuth2。我已经使用以下代码配置了网关安全性:

@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
@EnableCircuitBreaker
@EnableFeignClients
@EnableOAuth2Client
public class GatewayApplication extends WebSecurityConfigurerAdapter {

    private OAuth2ClientContext oauth2ClientContext;
    private SimpleUrlAuthenticationSuccessHandler simpleUrlAuthenticationSuccessHandler;
    private ScoreAuthorizationFilter scoreAuthorizationFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .antMatcher("/**")
                .authorizeRequests()
                .antMatchers("/", "/test", "/login**", "/webjars/**", "/error**")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and().logout().logoutSuccessUrl("/").permitAll()
                .and().addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class)
                .addFilterBefore(scoreAuthorizationFilter, BasicAuthenticationFilter.class)
        ;
    }

    private Filter ssoFilter() {
        OAuth2ClientAuthenticationProcessingFilter facebookFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/facebook");
        OAuth2RestTemplate facebookTemplate = new OAuth2RestTemplate(facebook(), oauth2ClientContext);
        facebookFilter.setRestTemplate(facebookTemplate);
        UserInfoTokenServices tokenServices = new UserInfoTokenServices(facebookResource().getUserInfoUri(), facebook().getClientId());
        tokenServices.setRestTemplate(facebookTemplate);
        facebookFilter.setTokenServices(tokenServices);
        facebookFilter.setAuthenticationSuccessHandler(simpleUrlAuthenticationSuccessHandler);
        return facebookFilter;
    }

    @Bean
    @ConfigurationProperties("facebook.client")
    public AuthorizationCodeResourceDetails facebook() {
        return new AuthorizationCodeResourceDetails();
    }

    @Bean
    @ConfigurationProperties("facebook.resource")
    public ResourceServerProperties facebookResource() {
        return new ResourceServerProperties();
    }

    @Bean
    public FilterRegistrationBean<OAuth2ClientContextFilter> oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
        FilterRegistrationBean<OAuth2ClientContextFilter> registration = new FilterRegistrationBean<OAuth2ClientContextFilter>();
        registration.setFilter(filter);
        registration.setOrder(-100);
        return registration;
    }

    @Bean
    public RequestInterceptor getFeignClientInterceptor() {
        return new FeignClientInterceptor();
    }

}

事实证明,用户的会话会在一段时间后过期。随着我深入挖掘,我发现 Facebook 不提供刷新令牌。相反,我们可以将短期令牌换成长期令牌 (Facebook long-lived token)。如何覆盖 Spring Security 中实现的标准 OAuth2 流程以向 Facebook 发送另一个请求以获取长期令牌,然后替换旧的访问令牌?

【问题讨论】:

    标签: spring facebook spring-boot oauth-2.0 spring-cloud


    【解决方案1】:

    你可以通过像这样扩展OAuth2ClientAuthenticationProcessingFilter类来实现你想要的:

    public class CustomAuthenticationProcessingFilter extends OAuth2ClientAuthenticationProcessingFilter {
    
        private ResourceServerTokenServices tokenServices;
    
        private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new OAuth2AuthenticationDetailsSource();
    
        private ApplicationEventPublisher eventPublisher;
    
        private AuthorizationCodeResourceDetails facebook;
    
        private String longLivedTokenUri;
    
        public CustomAuthenticationProcessingFilter(String defaultFilterProcessesUrl) {
            super(defaultFilterProcessesUrl);
            setAuthenticationDetailsSource(authenticationDetailsSource);
        }
    
        @Override
        public void setTokenServices(ResourceServerTokenServices tokenServices) {
            this.tokenServices = tokenServices;
            super.setTokenServices(tokenServices);
        }
    
        @Override
        public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
            this.eventPublisher = eventPublisher;
            super.setApplicationEventPublisher(eventPublisher);
        }
    
        @Override
        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
                throws AuthenticationException {
    
            OAuth2AccessToken accessToken;
            try {
                accessToken = restTemplate.getAccessToken();
            } catch (OAuth2Exception e) {
                BadCredentialsException bad = new BadCredentialsException("Could not obtain access token", e);
                publish(new OAuth2AuthenticationFailureEvent(bad));
                throw bad;
            }
            String longLivedToken = getFromFacebook(); //Get long lived token from facebook here
            try {
                OAuth2Authentication result = tokenServices.loadAuthentication(longLivedToken);
                if (authenticationDetailsSource != null) {
                    request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, longLivedToken);
                    request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_TYPE, accessToken.getTokenType());
                    result.setDetails(authenticationDetailsSource.buildDetails(request));
                }
                publish(new AuthenticationSuccessEvent(result));
                return result;
            } catch (InvalidTokenException e) {
                BadCredentialsException bad = new BadCredentialsException("Could not obtain user details from token", e);
                publish(new OAuth2AuthenticationFailureEvent(bad));
                throw bad;
            }
    
        }
    
        private void publish(ApplicationEvent event) {
            if (eventPublisher != null) {
                eventPublisher.publishEvent(event);
            }
        }
    }
    

    我希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2018-12-01
      • 2013-10-14
      • 2014-11-24
      • 2018-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-20
      相关资源
      最近更新 更多