不幸的是,我没有可以分享的示例应用程序,但这里是我希望有用的高级描述。
让我们暂时忘记您有一个 AngularJS 应用程序,并回顾一下 OpenID 身份验证交换的工作原理:
- 用户在登录表单中输入 OpenID URL 并提交到服务器
- 服务器获取 OpenID URL 并通过重定向到 OpenID 提供商进行响应。重定向包含一些参数,其中包括回调 URL。
- OpenID 提供商提示用户输入登录凭据,然后允许与服务器应用程序共享他/她的身份。
- OpenID 提供程序通过重定向回应用程序(在步骤 2 中作为回调给出的 URL)进行响应,并提供有关用户的信息,例如 ID、电子邮件、用户名等。
- 服务器现在拥有用户信息,并且可以通过唯一 ID、电子邮件地址或其他一些标识在自己的用户数据库中定位用户。此时,如果应用程序不知道该用户,则可以创建一个新帐户。
- 现在用户已知,服务器可以编写一个 cookie 来记录他/她是谁,但请注意,这是与第 5 步中的身份不同的身份。OpenID 提供商返回的身份信息对于定位用户很有用在您自己的数据库中,因此现在您可以在应用程序的上下文中记录用户的身份。这可以是数据库用户 ID、电子邮件地址或用户名(如果它们是唯一的)或令牌,令牌可以是您拥有的有关用户的一些信息的哈希值。
- 写入 cookie 后,发送到服务器的每个新请求都会附带标识经过身份验证的用户的数据。
那么让我们看看当您添加 AngularJS 时会发生什么。请注意,有很多方法可以做到这一点,我下面描述的是一种可能性。
如果 Angular 应用程序向服务器发出需要身份验证的请求,服务器应返回错误代码 401。例如,Angular 应用程序在收到 401 错误时可以弹出登录表单。
但是 OpenID 身份验证舞蹈无法在丰富的 JS 应用程序上下文中完成,因为它需要浏览器重定向。您的服务器端应用程序必须支持至少三种路由:
- 为 Angular 应用程序提供服务的根 URL
- 发起 OpenID 身份验证的 URL
- 作为回调发送给 OpenID 提供商的 URL
因此,用户连接到您的根 URL 并获取 AngularJS 应用程序,该应用程序以未经身份验证的状态启动。在某些时候,Angular 应用程序将提示用户使用具有 OpenID 文本字段和提交按钮的表单进行登录。这些表单字段应该是发布到服务器的常规 HTML 表单的一部分,而不是附加到控制器的客户端 Angular 元素。表单的“action”属性应指向服务器的 OpenID 登录路由。
当用户点击登录按钮时,服务器被唤醒并接收开始OpenID身份验证的请求。此时,上面的步骤 1-5 无需更改即可运行。
在第 5 步结束时,服务器已在应用程序的数据库中找到了用户。服务器现在可以做的就是重定向回根 URL 进行响应,以重新启动 Angular 应用程序。如果应用程序需要在非初始状态下重新启动,则可以在开始 OpenID 身份验证过程之前将要恢复的状态保存在客户端存储(例如 cookie)中。
但这还不够,服务器还需要向 Angular 传递有关登录用户的一些信息。实现此目的的一种方法是将用户的唯一 ID 或令牌附加到重定向 URL 的查询字符串中,Angular 应用程序可以使用权。这将与上面第 6 步中进入 cookie 的 ID 相同。
现在,Angular 应用程序已重新启动,可以在必要时恢复其状态,并且具有标识登录用户的 ID 或令牌。当应用程序需要向服务器发出 Ajax 请求时,它会随请求一起发送此 ID 或令牌。服务器可以对其进行验证,如果发现它无效或者如果它有过期日期并发现已过期,则返回 401。
如果随请求发送的标识得到验证,则可以执行该请求,并将响应发送回 Angular 应用程序。
只需删除用户 ID/令牌,即可在客户端实现注销功能,以便以后无需身份验证即可再次发送到服务器的请求。
很重要:Angular 应用程序和 Flask 服务器之间的所有交换(包括用户信息)都必须通过安全 HTTP 完成。否则,您的 ID 或令牌将以纯文本形式传输。