首页 > 解决方案 > 谷歌 oauth2 在春季启动时登录,null refreshToken,远程服务器失败,在本地主机中工作

问题描述

我在 java 11 中有一个工作代码,带有 spring security 和 google oauth login

@GetMapping("/google/integration")
public String googleIntegracionUsuario(@RegisteredOAuth2AuthorizedClient("google") OAuth2AuthorizedClient user, HttpServletRequest request, HttpServletResponse response) {
    System.out.println("\n\n RefreshToken: " + user.getRefreshToken().getTokenValue());
    System.out.println("\n\n AccessToken: " + user.getAccessToken().getTokenValue());
    return "hello user";
}

在@Configuration

@Override
    public void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .cors().and().csrf().disable()
                .authorizeRequests()
                .antMatchers("/google/integration").authenticated()
                .anyRequest().permitAll()
                .and()
                .oauth2Login()
                .authorizationEndpoint()
                .authorizationRequestResolver(new CustomAuthorizationRequestResolver(
                        this.clientRegistrationRepository));
    }

在 CustomAuthorizationRequestResolver


public class CustomAuthorizationRequestResolver implements OAuth2AuthorizationRequestResolver {
    private final OAuth2AuthorizationRequestResolver defaultAuthorizationRequestResolver;

    public CustomAuthorizationRequestResolver(
            ClientRegistrationRepository clientRegistrationRepository) {

        this.defaultAuthorizationRequestResolver =
                new DefaultOAuth2AuthorizationRequestResolver(
                        clientRegistrationRepository, "/oauth2/authorization");
    }

    @Override
    public OAuth2AuthorizationRequest resolve(HttpServletRequest request) {
        final OAuth2AuthorizationRequest authorizationRequest = this.defaultAuthorizationRequestResolver.resolve(request);
        return authorizationRequest != null ? customAuthorizationRequest(authorizationRequest) : null;
    }

    @Override
    public OAuth2AuthorizationRequest resolve(HttpServletRequest request, String clientRegistrationId) {
        final OAuth2AuthorizationRequest authorizationRequest = this.defaultAuthorizationRequestResolver.resolve(request, clientRegistrationId);
        return authorizationRequest != null ? customAuthorizationRequest(authorizationRequest) : null;
    }

    private OAuth2AuthorizationRequest customAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest) {

        Map<String, Object> additionalParameters = new LinkedHashMap<>(authorizationRequest.getAdditionalParameters());
        additionalParameters.put("access_type", "offline");

        return OAuth2AuthorizationRequest.from(authorizationRequest)
                .additionalParameters(additionalParameters)
                .build();
    }

}

并在 .properties

spring.security.oauth2.client.registration.google.client-id=clientIdValue
spring.security.oauth2.client.registration.google.client-secret=clientSecret
spring.security.oauth2.client.registration.google.scope=https://www.googleapis.com/auth/calendar,email,https://www.googleapis.com/auth/contacts.readonly

问题是在 localhost 中测试时一切运行顺利,但是当将项目上传到远程服务器时,刷新令牌为 NULL!

我没有远程服务器的域,但我编辑了 /etc/hosts 为远程服务器的公共 IP 提供了一个别名,并且我在谷歌控制台开发人员中将该别名添加到了 url 重定向

在远程服务器中,登录工作正常,用户实际上使用他/她的谷歌帐户登录,实际上我可以在远程服务器中获得用户的工作 accessToken,但是找不到刷新令牌,值只是为空!

System.out.println("\n\n AccessToken: " + uuser.getAccessToken().getTokenValue());
//prints: AccessToken: 'AccessToken value' in localhost and remoteServer
System.out.println("\n\n AccessToken: " + user.getRefreshToken().getTokenValue());
//prints: RefreshToken: 'RefreshToken value' in localhost
//Throws NullPointerException in remoteServer

标签: javaspring-securityspring-security-oauth2google-oauthgoogle-signin

解决方案


我发现远程服务器中的刷新令牌仅在用户第一次登录时获取值,这是 oauth2 框架的预期行为。但我不知道为什么我每次都在本地主机中始终获得刷新令牌,这让我感到困惑,我想这是因为它没有绑定到特定的 url


推荐阅读