如何在 redis-session 中持久化 OAuth2AuthorizedClient

How to persist OAuth2AuthorizedClient in redis-session

我的项目使用具有 spring 引导会话和 spring 安全性 5.1.10 的 redis 会话。我刚刚迁移了旧的 oauth2 实现。之前,当我重新启动应用程序时,我仍然有 access_token 和 refresh_token。使用此实现,用户已登录,但我在重新启动后松开了 AuthorizedClients,因此 loadAuthorizedClient 函数 returns null。同样在生产中,我们有许多具有相同应用程序的容器。有什么 springboot stardard 方法可以做到这一点吗?比如注册一些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>

注册一个 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();
    }