【问题标题】:How to persist OAuth2AuthorizedClient in redis-session如何在 redis-session 中持久化 OAuth2AuthorizedClient
【发布时间】:2020-09-05 16:19:22
【问题描述】:

我的项目使用带有 springboot session 和 spring security 5.1.10 的 redis session。我刚刚迁移了旧的 oauth2 实现。之前,当我重新启动应用程序时,我仍然拥有 access_token 和 refresh_token。使用此实现,用户已登录,但我失去了 AuthorizedClients,因此 loadAuthorizedClient 函数在重新启动后返回 null。同样在生产中,我们有许多具有相同应用程序的容器。有没有什么springboot标准的方法来实现这一点?比如注册一些 bean 什么的。

application.yml

    ...

    session:
        store-type: redis
        redis:
            namespace: spring:session:${spring.application.name}
    redis:
        host: ${redissession.host}
        password: ${redissession.password}
        port: ${redissession.port}

    security:
        oauth2:
            client:
                registration:
                    biocryptology:
                        provider: example
                        client-id: client
                        client-secret: xxx
                        client-authentication-method: basic
                        authorization-grant-type: authorization_code
                        redirect-uri-template: "{baseUrl}/login"
                        scope:
                            - openid
                provider:
                    example:
                        issuer-uri: https://....
    ...

Controller.java

        @Autowired
        private OAuth2AuthorizedClientService clientService;

        @GetMapping("/user")
        public String getOidcUserPrincipal() throws InvalidSessionException {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (!(authentication.getPrincipal() instanceof OidcUser)) {
                throw new InvalidSessionException();
            }

            OidcUser principal = ((OidcUser) authentication.getPrincipal());
            LOG.info("oidc: {}", principal.getName());

            OAuth2AuthenticationToken oauth2Token = (OAuth2AuthenticationToken) authentication;
            LOG.info("authentication: {}", oauth2Token);
            OAuth2AuthorizedClient client = clientService
                    .loadAuthorizedClient(oauth2Token.getAuthorizedClientRegistrationId(), authentication.getName());
            LOG.info("client: {}", client);

            return "logged";

        }

目标是跨容器获取 access_token 和 refresh_token,可能没有 OAuth2AuthorizedClientService 的任何其他方式?

编辑:

        <!-- Spring -->
        <spring-cloud.version>Greenwich.SR5</spring-cloud.version>

【问题讨论】:

  • 我也有同样的问题。您介意在此处列出确切的依赖项和版本吗?我尝试了您的解决方案,但它对我不起作用,所以我想比较库版本。谢谢。
  • @Sun,我编辑了帖子,我们使用项目之间共享的依赖管理器,我认为这些依赖关系已经足够信息了。这是入门安全版本: org.springframework.boot:spring-boot-starter-security:jar:2.1.14.RELEASE org.springframework.security:spring-security-oauth2-client:jar:5.1.10.RELEASE

标签: spring-boot oauth-2.0 microservices spring-security-oauth2 spring-session


【解决方案1】:

注册一个 bean 可以解决问题,它将它保存在会话中,但随后 OAuth2AuthorizedClientService 会因每种情况而崩溃,需要直接在会话中搜索或使用 OAuth2AuthorizedClientRepository 自动连接的解决方法:

    @Bean
    public OAuth2AuthorizedClientRepository authorizedClientRepository() {
        return new HttpSessionOAuth2AuthorizedClientRepository();
    }

controller.java

    @Autowired
    private OAuth2AuthorizedClientRepository clientRepository;

    @GetMapping("/user")
    public Map<String, Object> getOidcUserPrincipal(HttpServletRequest request) throws InvalidSessionException {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (!(authentication.getPrincipal() instanceof OidcUser)) {
            throw new InvalidSessionException();
        }

        OidcUser principal = ((OidcUser) authentication.getPrincipal());

        OAuth2AuthorizedClient client = clientRepository
                .loadAuthorizedClient(oauth2Token.getAuthorizedClientRegistrationId(), authentication, request);
        LOG.info("client: {}", client);
        if (Objects.nonNull(client)) {
            String token = client.getAccessToken().getTokenValue();
            String refreshtoken = client.getRefreshToken().getTokenValue();

            LOG.info("token: {} {}", token, refreshtoken);
        }

        return principal.getClaims();
    }

【讨论】:

  • 谢谢。这对我有用。我仍然不明白为什么我需要这种方法。我在应用程序 YML 中提供了所有需要的配置(显然)。
猜你喜欢
  • 2013-04-16
  • 2022-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-23
  • 2012-06-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多