Angular+Web API 应用程序中的会话管理
Posted
技术标签:
【中文标题】Angular+Web API 应用程序中的会话管理【英文标题】:Session Management in Angular+Web API application 【发布时间】:2018-03-03 13:02:04 【问题描述】:这就是我想要做的事情
我正在 Angular 中创建一个 SPA。
我所有的业务逻辑都是用 Web API 编写的。
我正在从 Angular 向 REST API 进行 http 调用,并获取 Json 数据并将其绑定到 Angular UI。
这一切都很好。此外我想在我的应用程序中实现会话维护。
一旦用户登录,我将调用另一个 api 来检查凭据是否正确,API 返回 true 或 false,根据将 Uesr 重定向到主页。
现在我需要维护用户的会话,除非用户注销。现在这是我知道的方法。
Cookie-> 我可以创建一个 cookie 来维护会话,但这样做有风险,并且可能有助于会话劫持。
注意:我不是在谈论令牌身份验证,我相信它具有完全不同的目的。
如果您能提出一些相关的建议,可能是使用 node.js 或我不知道的 Angular 中的东西,那将是一个很大的帮助。
如果您想对我所遵循的架构提出建议。这也很受欢迎。
【问题讨论】:
你试过浏览器localStorage吗? 浏览器上的任何东西都不安全。它并不比 cookie 更安全。 传统会话实际上由服务器管理并使用 cookie 进行跟踪。对于未直接连接到 Web 服务器本地存储的前端应用程序,cookie 和服务可能是一个不错的选择 对于经过身份验证的安全会话(登录用户),客户端证书提供最佳安全性。但是对于许多应用程序来说,这太过分了,但是如果通过 https 的 cookie 对您的需求来说太不安全了,您可以考虑这样的解决方案。 【参考方案1】:正如每个人都确认没有办法在 angularjs 中安全地保存客户端信息。我为我的网络应用所做的如下:
-
每当用户启动我的网络应用程序时,我都会使用 https://freegeoip.net/json/ 获取他/她的 IP 凭据。
第二步是使用他/她的 IP 地址创建一个唯一密钥(因为这对于每个用户来说都是唯一的)
登录时在请求参数中发送此密钥
在服务器端,我们检查了用户凭据并保存了此密钥以验证未来的请求,我们还生成了一个令牌来验证用户会话
在登录响应时,我们将生成的令牌保存在本地存储中。
下次用户启动应用程序时,我们从本地存储中获取令牌并使用 IP 生成唯一密钥。我们将两者都发送到服务器,它会验证令牌是否有效并与相同的唯一密钥相关联。
如果用户仍在同一网络上,则验证成功,否则不成功。
缺点
-
如果用户切换网络或他的 IP 地址更改服务器认为他/她已注销。
【讨论】:
【参考方案2】:对于大多数 AngularJS 应用程序,没有会话的概念。可能仍然存在身份验证和某种令牌,但存储会话信息(例如页面之间的表单内容)存储在浏览器中的 ram、cookie、会话存储或本地存储中。
最好的方法是本地存储,您可以使用 javascript 使用本地存储并将数据存储在变量中
https://www.npmjs.com/package/angular-local-storage
使用 API 调用从后端验证用户(不要忘记始终使用令牌调用 API),然后一旦 API 给出肯定响应,您将这些数据存储在浏览器本地存储中(这是普通的 javascript,您可以谷歌它)
这是从前端维护会话的方式。
只要它留在浏览器中,用户就会登录,如果他没有清除本地存储或注销。
当客户端从任何 REST API 收到 HTTP 状态 401 未经授权的响应时,角度控制器会清除所有 cookie 并将用户重定向到登录页面。当服务器有一段时间(比如 10 分钟)没有收到 app-token 时,服务器可能会发送 HTTP 状态 401 未授权响应。
【讨论】:
【参考方案3】:现在这是一个有趣的问题。
由于您使用 Angular,我假设您熟悉服务和工厂的工作方式。它们都充当单例,这意味着在任何时间点都只有一个实例。这意味着,例如,每当您将某些数据存储到工厂中时,它都会在您注入它的任何控制器中有效地为您提供状态。
假设您以一种非常具体的方式构建您的 SPA。大多数人不会过多地研究 Angular,而只是创建一个控制器,访问范围,在其中添加方法和东西,就这样,他们完成了。
现在假设您实际上将代码分开了一点。对于任何需要某些功能的东西,您可以将该代码放入一个服务中,然后将其注入任何需要它的控制器中。如果您获取一些数据并进行一些计算,您会将结果存储在服务中,并且该数据会保留在那里。当然,您可以在用户注销时删除所述数据。现在,如果用户使用 ctrl-f5 硬刷新页面,那么所有内容都会重新加载,并且在此之前保存的所有状态都会丢失。
如果您想在用户硬刷新之后保持状态,则必须考虑其他替代方案。
你可以使用本地存储,这是一个 html5 唯一的东西,这意味着只支持现代浏览器。
但是,您始终需要考虑的一件事是,您存储在客户端的任何内容都不会是真正安全的,因为它存在于不受您控制的客户端。
如果您不喜欢使用本地存储或 cookie 的想法(我不会为此责怪您),您将不得不引入另一个实际存储会话的层,这将是一个后端层。由于您使用 dot net,您可以创建一个简单的 MVC 应用程序,给它一些控制器,这些控制器可能会反映您的 web api 一个。您无需直接调用 Web api 控制器,而是调用 MVC 控制器。
这有什么帮助?好吧,Web Api 是无状态的,那里不会有会话,因为它没有任何意义。但是 Mvc 有 Session,你可以使用它。
因此,您添加 MVC,让您的 mvc 控制器调用 web api 控制器,它们返回 JsonResult,因此可以像调用 web api 一样调用它们并在服务器端安全地处理会话。
选择最适合您的解决方案。
【讨论】:
【参考方案4】:饼干是要走的路。会话劫持始终是一个问题,但可以缓解。使用长密钥作为会话密钥。并使用 HTTPS 网站。
【讨论】:
【参考方案5】:我猜你想说的是用户上下文,比如 Angular 的服务器端。
Angular 是一种客户端语言,客户端没有任何东西可以帮助您保存数据。
这完全取决于用户的判断
如果他删除 Cookies 和缓存,Local Storage 和 cookie 中的所有数据都会丢失。
您可以使用Shared Services 来帮助在您的应用程序中获取数据。或NGRX 请注意,如果用户硬刷新页面,所有数据都会消失。所以在这里你可能需要使用 Angular Local storage 或 cookies 之类的东西。
最好的设计是不使用所有这些,只实现共享服务或 Ngrx 套件并检查用户是否已注销,如果是,则将他再次重定向到登录屏幕。并在服务器端使用上下文。
希望对你有所帮助。
【讨论】:
【参考方案6】:以防万一我理解你的情况......
将密钥存储在安全 cookie 中,您可以将其称为令牌(从 node.js 服务器完成) 您可以从请求客户端的指纹生成此令牌 https://www.npmjs.com/package/request-object-fingerprint
对于每个请求,客户端代码都不需要发送令牌。对于 Obvious,服务器将根据服务器的能力将令牌与用户的身份一起保存在数据库/缓存中。
要回答是否有人窃取了令牌,您可以使用请求客户端的指纹进行检查,如果不匹配,您可以使会话无效并按照要求进行操作。
【讨论】:
以上是关于Angular+Web API 应用程序中的会话管理的主要内容,如果未能解决你的问题,请参考以下文章
.NET Core Web API / Angular 应用程序中的 Windows 身份验证
ASP.NET 核心 Web API 和 Angular 客户端中的外部身份验证
Angular2 中的 Http PUT 到 .NET Core Web API 提供来自预检请求的 http 401 错误