首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Spring boot安全,Oauth2将访问令牌替换为facebook的长寿令牌

Spring boot安全,Oauth2将访问令牌替换为facebook的长寿令牌
EN

Stack Overflow用户
提问于 2019-02-21 13:18:49
回答 1查看 564关注 0票数 4

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

代码语言:javascript
运行
复制
@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发送另一个请求,以获取长期令牌,然后替换旧的访问令牌?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-23 22:29:00

您可以通过如下方式扩展OAuth2ClientAuthenticationProcessingFilter类来实现您想要的功能:

代码语言:javascript
运行
复制
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);
        }
    }
}

我希望这能帮到你。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54799754

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档