将客户端社交登录和服务器端授权与 Cordova 和 Node.js 相结合
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
- 《从零手撸:仿小红书(微服务架构)》 已完结,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 100w+ 字,讲解图 4013+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3700+ 小伙伴加入学习 ,欢迎点击围观
我相信这赢得了有史以来最长博客标题的称号。那我到底在说什么?向 Apache Cordova 应用程序添加社交登录方面并不难。我过去使用过各种插件/库,而且大部分情况下——它只是简单的工作。但是最近我遇到了一个我不知道如何解决的问题。鉴于您的移动客户端根据某些 OAuth 提供程序对用户进行身份验证,并且您 随后 允许该用户与您的服务器进行交互,如何 a) 确保运行服务器 API 的人经过身份验证以及 b) 您如何唯一地识别用户?这有点抽象,那么举个真实的例子怎么样?
想象一下,您正在构建一个允许用户写笔记的移动应用程序。虽然您可以将笔记存储在客户端上,但您确实需要将它们存储在您自己的后端存储中。为了确保只有经过身份验证的用户才能访问您的服务器 API,您可以构建自己的用户系统,让用户登录(当然是通过 https),将会话变量与他们的帐户信息一起存储,以及他们何时创建数据(或尝试读取数据),使用某种主键来获取正确的数据。
这是相当样板。但是,当您在客户端混合使用社交登录时会发生什么?在这种情况下,移动应用程序会处理对提供者的 OAuth 请求,而提供者会返回一个令牌。所以在客户端你知道当前用户是犹太洁食。但是,当她向您的 Node(或 ColdFusion、PHP 等)服务器发出请求时,您如何知道用户已登录——甚至更好——如何获得该用户的唯一标识符,以便您可以正确处理他们的请求数据操作。
我做了一些搜索,发现了这个 Stackoverflow 帖子/答案: iOS & node.js: how to verify passed access token? .用户 Gijs 回应说,不同的 OAuth 提供者有不同的方法来验证访问令牌。所以我们的想法是将令牌传递给您的后端服务器,验证它,然后获得一个唯一的 ID。
我决定试一试并构建一个简单的概念证明。这非常粗糙,但可以让您了解如何执行此操作的基本概念。对于我的 POC,我决定使用 Christophe Coenraet 的 OpenFB 库。它是一个处理 OAuth 的无插件 JavaScript 库。最近我也使用了 ng-cordova-oauth ,但我想尝试一些不同的东西。我用两个简单的按钮创建了一个快速的 Ionic 应用程序:
第一个按钮触发 OAuth 进程。当然,我按照 Christophe 的指示首先创建了我的 Facebook 应用程序:
这背后的代码非常简单:
$scope.doLogin = function() {
console.log("DoLogin");
openFB.login(
function(response) {
if(response.status === 'connected') {
$scope.token = response.authResponse.accessToken;
console.log('Token stored: ',response);
alert('Ok, try to make a call now');
} else {
alert('Facebook login failed: ' + response.error);
}
}, {scope: 'email'});
}
请注意,我存储了访问令牌,以便稍后使用。接下来——我们需要调用服务器。如果我没记错的话,Angular 提供了一种修改 所有 HTTP 请求以包含内容的方法。现在,我保持简单,只是将令牌作为表单帖子的一部分包含在内。
$scope.doLogin = function() {
console.log("DoLogin");
openFB.login(
function(response) {
if(response.status === 'connected') {
$scope.token = response.authResponse.accessToken;
console.log('Token stored: ',response);
alert('Ok, try to make a call now');
} else {
alert('Facebook login failed: ' + response.error);
}
}, {scope: 'email'});
}
好的,到目前为止一切顺利。现在让我们转到节点端。正如我上面链接到的 StackOverflow 帖子中提到的,您可以使用令牌向 graph.facebook.com 发出请求,如果您得到正确的响应,您就知道一切顺利。我写了一个函数,以后可以用于中间件。它将测试缓存在会话范围内,这看起来很安全,但也许这不是一个好主意。
此处需要注意的事项:我特别要求回复电子邮件地址。我的结果是这样的:
{ email: 'raymondcamden@gmail.com', id: 'abigassnumber' }
理论上,ID 是足够唯一的。但是,如果我使用多个不同的 oauth 提供商,我可以改为使用电子邮件作为主键。这样一来,只要两个帐户使用相同的电子邮件地址,您就可以通过 Facebook 或 Twitter 登录并拥有相同的数据。请注意,我实际上 并未 存储该电子邮件地址。我会在一个真正的应用程序中。最后,这是我从移动应用程序调用的路由:
$scope.doLogin = function() {
console.log("DoLogin");
openFB.login(
function(response) {
if(response.status === 'connected') {
$scope.token = response.authResponse.accessToken;
console.log('Token stored: ',response);
alert('Ok, try to make a call now');
} else {
alert('Facebook login failed: ' + response.error);
}
}, {scope: 'email'});
}
这是毫无意义的,但至少演示了使用安全功能来包装路由。
正如我所说——这很粗糙——但对我来说 似乎 很有意义。你呢?