java - 谷歌 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
解决方案
我发现远程服务器中的刷新令牌仅在用户第一次登录时获取值,这是 oauth2 框架的预期行为。但我不知道为什么我每次都在本地主机中始终获得刷新令牌,这让我感到困惑,我想这是因为它没有绑定到特定的 url
推荐阅读
- android - 如何为不同的 SDK 同时拥有 Android-Support 和 Android-X
- c# - 通过中间件记录 web api 请求时如何获取当前用户的 id
- c# - ReadKey 在线程超时结束之前获取字符
- pine-script - 这个 pine 脚本代码不理解公式和含义
- python - Kubernetes Python 客户端 API 是否支持多线程?
- class - Haxe 访问类
静态字段 - sql - 使用带有更新语句的子查询
- numpy - 更快地将 Matplotlib 图转换为 Numpy 数组
- java - Java String#split() - 创建内存泄漏
- android - 如何在 Flutter 的地图上绘制从源到目的地的路径?