如何实现 Java OAuth 2.0 以登录 GitHub 和 Google

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

我们添加到 takipi 的最新功能之一是第三方登录。如果你像我一样懒惰,那么我猜你也更喜欢跳过填写表格和 设置新密码 。如果可用,许多人更喜欢第三方登录,只要他们要求的权限是非侵入性的——没有人真的希望随机帖子出现在他们的 Facebook 墙上,所以这种访问只包括用户的姓名和电子邮件地址等基本信息。在这篇文章中,您将了解到我们如何在 takipi 中实现这一点,如何在您的应用程序中使用 3rd 方登录以及我们遇到的一些见解,如果您决定集成,这些见解将为您节省一些宝贵的时间这与您自己的应用程序。

新帖子:如何实现 java oauth 2.0 以使用 github 和 google 登录 http://t.co/20hn59dctf pic.twitter.com/3tnnwpkjet

- takipi (@takipid) 2015 年 5 月 14 日

在我们自己的小宇宙中,事实证明我并不孤单,我们的许多用户也有同感。由于我们是一家开发工具初创公司,因此使用 github 和谷歌的第 3 方登录非常有意义。除了为您的用户带来便利之外,使用第三方服务还可以增强他们的安全性。由于 google 和 github 使用双因素身份验证 (2fa),您的应用程序可以“免费”享受这种级别的安全性。在我们的例子中,我们已经启用了 2fa,所以我想这让我们...... 3fa。


使用第 3 方登录按钮预览我们新主页的模型

要了解它在实践中的工作原理,您可以 查看我们用于内部测试的页面 。它完全有效,但更新尚未在网站上发布。您在这里有难得的机会成为第一个使用它的人。

所以提醒我 oauth 2.0 是如何再次出现的?

oauth 登录流程是这样的:用户访问您的站点,单击“使用任何方式登录”按钮并被重定向到权限页面。权限页面来自 whatever™,当他们批准您请求的权限时,whatever™ 向他们发送一个令牌,然后他的浏览器将该令牌发送到您的应用程序的后端。一旦您拥有了令牌,您就可以将它发送回 whatever™ 进行验证并假设它已经过验证——您可以访问您被授予权限的数据。

谷歌 oauth2.0 库

为了在我们的网站上实施第 3 方登录,我们使用了 google 的 java api 客户端库 。它还有 jackson2、protobuf 和出现在 github 顶级 java 项目使用的前 100 个库中的 各种其他方便的实用程序。这对我们来说是一个非常直接的选择,因为我们已经将这个库用于其他目的,而且,老实说,谷歌库刚刚成为……谷歌的第一个结果。准备好你的 锡纸帽子

使用谷歌实现登录

这是旅途中最轻松的部分;谷歌一端的 文档 清晰明了。因为它是他们自己的库,所以他们还抽象了部分过程并在幕后处理它,使其更容易实现。第一步是在 谷歌的开发者控制台 上创建一个项目,您可以在其中注册您的应用程序并自定义权限页面。


google 的权限页面 – 为 takipi 定制

现在回到java。从本质上讲,该过程可以归结为几个简单的步骤,毫不奇怪。首先,我们构建并执行请求以获取 googletokenresponse,以便我们可以验证从用户那里获得的令牌。然后我们使用此响应创建一个 googlecredential ,让我们对其调用 getaccesstoken() 并以 json 格式返回用户信息:


 jsonfactory jsonfactory = new jacksonfactory();
httptransport httptransport = new nethttptransport();

googletokenresponse tokenresponse = new googleauthorizationcodetokenrequest( httptransport, jsonfactory, /* client id and secret */, code, "postmessage").execute();

googlecredential credential = new googlecredential.builder() .setjsonfactory(jsonfactory) .settransport(httptransport) .setclientsecrets(/* client id and secret */).build() .setfromtokenresponse(tokenresponse);

oauth2 oauth2 = new oauth2.builder(httptransport, jsonfactory, credential).setapplicationname("yourappname").build(); tokeninfo tokeninfo = oauth2.tokeninfo().setaccesstoken(credential.getaccesstoken()).execute();

return oauth2.userinfo().get().execute();

繁荣。就是这样。这里最好的建议是只遵循官方文档。在 github 的最后,实现变得有点棘手。

使用github实现登录

现在我们意识到 google 帮助我们在 oauth 方面走捷径,并使用 googletokenresponse 和 googlecredential 的抽象。使用 github,我们必须更接近原始协议。与谷歌类似,我们可以在 github 的 开发者应用程序屏幕 上注册我们的应用程序时自定义权限屏幕。

github的权限页面——为takipi定制

当我们得到实际代码时,有 3 个主要问题使我们的速度有所降低,而且我们 在文档中 找不到。这是我们解决它们的方法:

1.建立自己的请求流程

在谷歌的案例中只有 5 行代码变成了 19 行,这样我们就可以生成一个 github 令牌响应。以下是自己构建请求的方法:


 jsonfactory jsonfactory = new jacksonfactory();
httptransport httptransport = new nethttptransport();

googletokenresponse tokenresponse = new googleauthorizationcodetokenrequest( httptransport, jsonfactory, /* client id and secret */, code, "postmessage").execute();

googlecredential credential = new googlecredential.builder() .setjsonfactory(jsonfactory) .settransport(httptransport) .setclientsecrets(/* client id and secret */).build() .setfromtokenresponse(tokenresponse);

oauth2 oauth2 = new oauth2.builder(httptransport, jsonfactory, credential).setapplicationname("yourappname").build(); tokeninfo tokeninfo = oauth2.tokeninfo().setaccesstoken(credential.getaccesstoken()).execute();

return oauth2.userinfo().get().execute();

2. 期待 json 响应?由于某种原因,字符串是默认值

注意到前面的初始化方法会设置接受吗?这有点令人惊讶。结果你需要明确要求 github 以 json 格式将响应发回给你,否则你将以字符串格式获得它。如果我们提前知道它可以节省我们一些时间来查看它:


但谢天谢地,我们找到了一些胶带和回形针来处理事情


3.处理github登录的用户邮件

现在,一位 github 用户可能拥有多个电子邮件地址,然后您必须选择要用于您自己目的的电子邮件地址。出于这个原因,我们创建了一个 getbestemail 方法来整理电子邮件数组(注意它应该扩展 arraylist 才能工作)。在对电子邮件数组进行排序后,我们选择了我们能找到的最佳选项:


 jsonfactory jsonfactory = new jacksonfactory();
httptransport httptransport = new nethttptransport();

googletokenresponse tokenresponse = new googleauthorizationcodetokenrequest( httptransport, jsonfactory, /* client id and secret */, code, "postmessage").execute();

googlecredential credential = new googlecredential.builder() .setjsonfactory(jsonfactory) .settransport(httptransport) .setclientsecrets(/* client id and secret */).build() .setfromtokenresponse(tokenresponse);

oauth2 oauth2 = new oauth2.builder(httptransport, jsonfactory, credential).setapplicationname("yourappname").build(); tokeninfo tokeninfo = oauth2.tokeninfo().setaccesstoken(credential.getaccesstoken()).execute();

return oauth2.userinfo().get().execute();

那么最好的选择是什么?我们从 github 的响应中获得的电子邮件数组中的每个字段都有一个电子邮件、一个已验证的字段和一个主要字段。这是我们为排序而实现的排序比较器:


 jsonfactory jsonfactory = new jacksonfactory();
httptransport httptransport = new nethttptransport();

googletokenresponse tokenresponse = new googleauthorizationcodetokenrequest( httptransport, jsonfactory, /* client id and secret */, code, "postmessage").execute();

googlecredential credential = new googlecredential.builder() .setjsonfactory(jsonfactory) .settransport(httptransport) .setclientsecrets(/* client id and secret */).build() .setfromtokenresponse(tokenresponse);

oauth2 oauth2 = new oauth2.builder(httptransport, jsonfactory, credential).setapplicationname("yourappname").build(); tokeninfo tokeninfo = oauth2.tokeninfo().setaccesstoken(credential.getaccesstoken()).execute();

return oauth2.userinfo().get().execute();

所以基本上你可以看到我们更喜欢经过验证的和主要的电子邮件。

结论

我们希望这篇文章能帮助您了解如何通过 google 和 github 的登录来处理 oauth 和 java。虽然这是我们决定实施它的方式,但您可以使用其他方式和库来实现类似的结果。我们很高兴听到您采用了哪种方法,您更喜欢哪些库,并回答有关此实现的任何问题。如果您对我们决定这样做的方式有任何意见或建议,请在下面的评论部分告诉我。如果您发现自己遇到麻烦,请分享您遇到的问题,我们很乐意提供帮助并分享更多代码。

帮助您更好地了解环境的 15 种工具—— 查看工具列表