正如我所怀疑的,事实证明这是Scope 的问题。
首先,让我告诉您,我通常喜欢 Google 出色的文档和 API,但在某些情况下,看似微不足道的细节被认为是理所当然的,开发人员想自己调试它们。我觉得,这是其中一个问题。
因此,任何启动 Google 登录集成的人都将阅读官方文档和指南,并且在文档中有提及和使用范围,但类似以下内容:
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestServerAuthCode(CLIENT_ID, true)
.requestScopes(new Scope(Scopes.DRIVE_APPFOLDER), new Scope(Scopes.PROFILE), new Scope(Scopes.EMAIL))
.requestEmail()
.requestProfile()
.requestIdToken(CLIENT_ID)
.build();
这是来自一个示例 sn-p。当然,开发人员从示例 sn-p 复制并进一步扩展它。那么,作为开发人员,我该如何扩展呢?
嗯,对于初学者来说,我显然可以通过更多范围,对吧?
没错,我做到了,但仍然被这个问题所困扰。毕竟,我所要做的就是添加适当的范围权限。怎么会有人受到这样的打击?让我向您展示Scopes 类的样子:
public final class Scopes {
public static final java.lang.String PROFILE = "profile";
public static final java.lang.String EMAIL = "email";
public static final java.lang.String PLUS_LOGIN = "https://www.googleapis.com/auth/plus.login";
public static final java.lang.String PLUS_ME = "https://www.googleapis.com/auth/plus.me";
public static final java.lang.String GAMES = "https://www.googleapis.com/auth/games";
public static final java.lang.String CLOUD_SAVE = "https://www.googleapis.com/auth/datastoremobile";
public static final java.lang.String APP_STATE = "https://www.googleapis.com/auth/appstate";
public static final java.lang.String DRIVE_FILE = "https://www.googleapis.com/auth/drive.file";
public static final java.lang.String DRIVE_APPFOLDER = "https://www.googleapis.com/auth/drive.appdata";
public static final java.lang.String FITNESS_ACTIVITY_READ = "https://www.googleapis.com/auth/fitness.activity.read";
public static final java.lang.String FITNESS_ACTIVITY_READ_WRITE = "https://www.googleapis.com/auth/fitness.activity.write";
public static final java.lang.String FITNESS_LOCATION_READ = "https://www.googleapis.com/auth/fitness.location.read";
public static final java.lang.String FITNESS_LOCATION_READ_WRITE = "https://www.googleapis.com/auth/fitness.location.write";
public static final java.lang.String FITNESS_BODY_READ = "https://www.googleapis.com/auth/fitness.body.read";
public static final java.lang.String FITNESS_BODY_READ_WRITE = "https://www.googleapis.com/auth/fitness.body.write";
public static final java.lang.String FITNESS_NUTRITION_READ = "https://www.googleapis.com/auth/fitness.nutrition.read";
public static final java.lang.String FITNESS_NUTRITION_READ_WRITE = "https://www.googleapis.com/auth/fitness.nutrition.write";
private Scopes() { /* compiled code */ }
}
所以,开发人员认为,
“这些都是支持的范围,我所要做的就是参考一个
有效范围为Scopes.SCOPE_NAME"
但你猜怎么着? Scopes 的故事还有更多内容!
事实证明,您可以使用您所定位的 Google API 端点创建自己的范围。就我而言,我使用的是联系人 API,因此新代码如下所示:
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestServerAuthCode(CLIENT_ID, true)
.requestScopes(new Scope(Scopes.DRIVE_APPFOLDER), new Scope(Scopes.PROFILE), new Scope(Scopes.EMAIL), new Scope("https://www.google.com/m8/feeds/"))
.requestEmail()
.requestProfile()
.requestIdToken(CLIENT_ID)
.build();
你有没有注意到额外的作用域:
new Scope("https://www.google.com/m8/feeds/")
是的,就是这样。这就是答案。
那么,到底是什么让我的蜘蛛侠感觉刺痛了?
您可以看到,在 Google 提供的上述权限页面中,它没有提及任何有关联系人的内容。但是,我想访问联系人。这是一个明显的危险信号!
添加附加范围后,它显示“想要管理你的联系人”。(你的啊哈!时刻)
最后一件事 -
我是如何知道 Scope 的 URI 的?
嗯,这很容易。您最有可能在您所针对的相应 API 的文档/指南中找到它。另外,请在提供的示例中注意它。因此,下次您遇到身份验证问题时,首先要寻找正确的范围。