Spring 5 Google OAuth2需配置HTTPS回调URL而非HTTP的解决方案
我的站点部署在Apache httpd(端口80、443)和Wildfly 15(端口8080)上,Apache通过以下反向代理配置与Wildfly通信:
ProxyPass / http://myhost.com:8080/ ProxyPassReverse / http://myhost.com:8080/
我把基于Java 11的Spring 5应用打成WAR包部署在Wildfly上,应用用Google OAuth2实现用户认证。现在要调用YouTube API,但这类API要求授权回调URI必须是HTTPS。目前只有配置http://myhost.com:8080/login/oauth2/code/google才能正常登录,这和YouTube API的要求冲突。
我明白回调用HTTP+8080是因为请求来自Wildfly上的应用,但我需要把回调URI改成https://myhost.com/login/oauth2/code/google,该怎么配置?
以下是我已有的配置,但没生效:
现有Spring Security配置
@PropertySource("classpath:application.properties") @Configuration @EnableWebSecurity public class SecurityConfiguration { @Value("${spring.security.oauth2.client.registration.google.redirect-uri}") private String redirectUri; @Bean public SecurityFilterChain filterChain( HttpSecurity http) throws Exception { http.cors().and().csrf().disable()// .authorizeRequests()// .antMatchers("/secure/**").authenticated()// .antMatchers("/api/**", "/login/**").permitAll()// for redirectUri .antMatchers("/**").permitAll()// .antMatchers("/logout").permitAll()// .and()// .sessionManagement()// .sessionCreationPolicy(SessionCreationPolicy.ALWAYS) .and()// .userDetailsService(userDetailsManager())// .oauth2Login()// because we need to authorize our users, not just be a web client //.oauth2Client()// not this .redirectionEndpoint().baseUri(this.redirectUri)// .and()// .clientRegistrationRepository(this.securityService.getClientRegistrationRepository())// .authorizedClientService(this.securityService.getAuthorizedClientService())// .loginPage(SecurityController.LOGIN_PAGE_MAPPING)// .defaultSuccessUrl(loginSuccessUrl)// //.successHandler(this.loginSuccessHandler)// .failureUrl("/login-failure-page")// .and()// .logout()// .clearAuthentication(true)// .invalidateHttpSession(true)// .deleteCookies("JSESSIONID")// .logoutSuccessUrl(SecurityController.LOGOUT_PAGE_MAPPING).permitAll() // Gotta get back to the correct port after login. .and()// .requestCache().requestCache(requestCache()); // port mapper here // For Firefox and h2-console http.headers().frameOptions().disable(); return http.build(); } }
application.properties配置
spring.security.oauth2.client.registration.google.redirect-uri=https://myhost.com/login/oauth2/code/google spring.security.oauth2.client.registration.google.redirectUri=https://myhost.com/login/oauth2/code/google spring.security.oauth2.client.registration.google.preEstablishedRedirectUri=https://myhost.com/login/oauth2/code/google spring.security.oauth2.client.use-current-uri=false
CORS配置
@Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings( CorsRegistry registry) { registry.addMapping("/**")// .allowedOrigins(/*"http://myhost.com:8080",*/ "https://myhost.com", "https://myhost.com:8080")// .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH"); } }; }
要解决这个问题,得从Apache反向代理和Spring应用内部两个层面调整,确保Spring能识别外部的HTTPS请求,同时正确生成符合要求的回调URI。
1. 完善Apache反向代理配置
当前的代理配置没传递HTTPS相关头信息,导致Wildfly/Spring误以为请求是HTTP的。需要添加头信息让Spring知道外部是HTTPS协议:
ProxyPass / http://myhost.com:8080/ ProxyPassReverse / http://myhost.com:8080/ # 传递HTTPS协议和端口信息 RequestHeader set X-Forwarded-Proto "https" RequestHeader set X-Forwarded-Port "443" # 传递正确的Host头,避免Spring生成错误的URI RequestHeader set Host "myhost.com"
注意要确保Apache的mod_headers模块已经启用(可以用a2enmod headers命令启用)。
2. 让Spring识别反向代理的HTTPS请求
Spring需要知道自己运行在反向代理之后,要启用ForwardedHeaderFilter来处理上面添加的X-Forwarded-*头:
@Bean public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() { FilterRegistrationBean<ForwardedHeaderFilter> filterRegistrationBean = new FilterRegistrationBean<>(); filterRegistrationBean.setFilter(new ForwardedHeaderFilter()); // 设置最高优先级,确保先处理头信息 filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); return filterRegistrationBean; }
如果是Spring Boot环境,也可以直接在application.properties里加配置:
server.forward-headers-strategy=NATIVE
3. 简化OAuth2回调URI配置
你当前的application.properties里有重复配置,只保留必要的即可,同时确保和Google控制台的配置一致:
# 只保留这一行,和Google控制台里的回调URI完全匹配 spring.security.oauth2.client.registration.google.redirect-uri=https://myhost.com/login/oauth2/code/google # 禁用自动使用当前请求URI,强制用配置的固定值 spring.security.oauth2.client.use-current-uri=false
同时,去Google Cloud控制台的OAuth2客户端配置页面,把回调URI更新为https://myhost.com/login/oauth2/code/google,删掉旧的HTTP+8080的条目。
4. 调整SecurityFilterChain配置
不需要手动给redirectionEndpoint指定完整的URL,Spring会根据识别到的外部协议自动生成正确的回调URI,把这部分代码修改为:
.oauth2Login() // 移除手动设置的baseUri,让Spring自动处理 // .redirectionEndpoint().baseUri(this.redirectUri).and() .clientRegistrationRepository(this.securityService.getClientRegistrationRepository()) .authorizedClientService(this.securityService.getAuthorizedClientService()) // 其余配置保持不变
5. 优化CORS配置(可选)
当前CORS配置里的https://myhost.com:8080可以移除,因为外部用户只会通过443端口访问:
@Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("https://myhost.com") .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH"); } }; }
验证步骤
- 重启Apache和Wildfly服务
- 访问
https://myhost.com尝试登录,检查Google授权页面显示的回调URI是否为HTTPS格式 - 登录成功后,测试YouTube API的调用是否正常
内容的提问来源于stack exchange,提问作者Gary Kephart

