Spring Social Security(XML配置)社交登录数小时后失效问题咨询
我之前维护Spring Social项目时也碰到过几乎一模一样的问题,结合对Spring Social OAuth2流程的理解和踩过的坑,给你几个针对性的排查和解决方向:
1. 先排查Google API版本问题(最可能的诱因)
你调用的https://www.googleapis.com/plus/v1/people/me接口已经被Google正式废弃了,初期可能还能正常请求,但Google会逐步限制对旧API的访问,这就解释了为什么运行数小时后突然失效——Google那边的限流或权限拦截生效了。
解决办法:
- 升级Spring Social Google的依赖到最新稳定版,新版已经切换到了People API。
- 如果无法升级依赖,就自定义
ApiAdapter来调用People API的https://people.googleapis.com/v1/people/me接口,替代原有的Plus API调用逻辑(代码示例如下):
public class CustomGoogleUserAdapter extends GoogleAdapter { @Override public UserProfile fetchUserProfile(Google google) { // 调用People API获取用户信息 Person userPerson = google.peopleOperations() .getPerson("me", Arrays.asList("emailAddresses", "names")); UserProfileBuilder profileBuilder = new UserProfileBuilder(); profileBuilder.setEmail(userPerson.getEmailAddresses().get(0).getValue()); profileBuilder.setName(userPerson.getNames().get(0).getDisplayName()); profileBuilder.setFirstName(userPerson.getNames().get(0).getGivenName()); profileBuilder.setLastName(userPerson.getNames().get(0).getFamilyName()); return profileBuilder.build(); } }
然后在XML配置里把这个自定义适配器绑定到Google连接工厂:
<bean id="googleConnectionFactory" class="org.springframework.social.google.connect.GoogleConnectionFactory"> <constructor-arg value="${google.client.id}"/> <constructor-arg value="${google.client.secret}"/> <property name="scope" value="email profile offline_access"/> <property name="apiAdapter"> <bean class="com.yourpackage.CustomGoogleUserAdapter"/> </property> </bean>
2. 确保ConnectionFactory是单例(核心配置坑)
Spring Social的ConnectionFactory默认应该是单例的,但如果你的XML配置不小心把它定义成了原型(prototype),或者通过其他方式重复创建实例,会导致OAuth2的token缓存、客户端状态管理混乱,运行一段时间后就会出现认证失效。
检查你的XML配置:
- 确保
<google:connection-factory>或自定义的GoogleConnectionFactorybean没有设置scope="prototype",默认的singleton是正确的。 - 确认
ConnectionFactoryRegistry(连接工厂定位器)只初始化一次,没有被重复创建。
3. 配置Offline Access权限,让Token自动刷新
如果你的应用没有请求offline_access权限,Google只会返回短期的access token,过期后无法自动刷新,导致后续调用API失败。而重启Tomcat会重新发起授权流程,拿到新的token,所以暂时恢复正常。
解决办法:
- 在Google开发者控制台的应用OAuth权限里,确保添加了
offline_access权限。 - 在Spring Social的Google连接工厂配置里,显式指定scope包含
offline_access(如上面的XML示例),这样Spring Social会自动处理token的刷新逻辑,不用手动干预。
4. 排查会话与连接信息存储问题
如果你的ConnectionRepository(用户连接信息存储)配置有问题,比如用了内存存储(默认的InMemoryUsersConnectionRepository),Tomcat运行一段时间后内存中的连接信息丢失,或者数据库连接池耗尽导致无法持久化连接数据,都会引发认证失效。
建议:
- 改用
JdbcUsersConnectionRepository持久化连接信息到数据库,避免内存存储的局限性。 - 检查数据库连接池的配置,确保有足够的连接数,不会因为连接耗尽导致无法读写连接数据。
- 检查Tomcat的会话超时设置,如果会话超时时间过短,Spring Social保存的授权状态会丢失,导致重定向到默认的
/signin而不是指定的redirect_uri。
5. 检查Redirect URI的一致性
确保Google开发者控制台里配置的redirect_uri和Spring Social配置的完全一致,包括协议(http/https)、域名、端口和路径。如果应用部署在反向代理后面,还要确保Spring Social能正确获取外部的请求URL,避免生成错误的redirect_uri。
可以在XML里显式指定redirect_uri:
<google:connection-factory client-id="${google.client.id}" client-secret="${google.client.secret}" redirect-uri="https://yourdomain.com/signin/google"/>
按照上面的步骤逐一排查,应该能解决这个“时好时坏”的问题。我当时是因为用了废弃的Plus API,加上没配置offline_access权限,导致运行一段时间后被Google拦截,替换API并调整权限后就彻底解决了。
内容的提问来源于stack exchange,提问作者indur

