Flask-Login的request_loader如何与user_loader相关联?

12

提前道歉,我的问题可能有点晦涩。尽管我看了很多资料,仍然无法理解。如果您能解释一下将会非常好。

在 Flask-Login 中,request_loader 的目的是什么?它如何与 user_loader 装饰器交互?

如果我使用基于令牌的身份验证系统(我计划将令牌发送到我的 AngularJS 前端,在那里存储令牌并将该令牌发送到授权标头中),我是否需要一个 request_loader,还是只需要一个 user_loader(在其中检查 auth 标头并查看用户是否存在)就足够了?


我对做同样的事情很感兴趣。 - Zach Siegel
我计划将令牌发送到我的AngularJS前端,将令牌存储在那里,并在授权令牌标头中发送该令牌。我也对此感兴趣!您能否澄清如何使用request_loader来实现此目的?Angular的$http是否自动使用与其他浏览器请求相同的cookie?我们需要执行“将令牌发送到我的AngularJS前端”的部分吗?我的担忧是会话ID可能会在不同的标头或参数中发送(这就是为什么我可能需要request_loader)-但是已登录的浏览器是否仍会自动发送它? - Zach Siegel
1
嗨Zach,抱歉回复晚了。据我所知,您实际上不需要同时拥有用户加载器和请求加载器。用户加载器非常简单,它检查会话所归属的user_id,并检查该user_id是否存在于您的用户数据库中并进行身份验证。请求加载器检查请求授权头并执行相同的身份验证。因此,对于大多数具有任何类型的用户会话管理的应用程序,您将不需要请求加载器。您无需发送任何令牌... Flask和Angular JS将自动处理这些问题与user_loader。 - galeej
嗨galeej - 我找到了一种更加流畅的解决方案。我会将其作为自己的答案发布。 - Zach Siegel
3个回答

11

来自 Flask-Login 文档:

有时您想要登录用户而不使用 cookie,例如使用标题值或作为查询参数传递的 api 密钥。在这些情况下,您应该使用 request_loader 回调函数。此回调函数应与您的 user_loader 回调函数相同,只是它接受 Flask 请求而不是 user_id。

因此,回答您的问题,它们都为 Flask-Login 提供相同的功能。它们都用于加载用户。然而,request_loader 适用于自定义登录。

这是一个很棒的教程,我发现它利用了 request_loader 来利用基于令牌的身份验证(这篇文章不是我自己的,我只是分享链接):http://gouthamanbalaraman.com/blog/minimal-flask-login-example.html


3
我需要澄清一下。 这就是为什么你应该在flask_login中使用request_loader的原因。
在你的api中会有很多来自flask_login的@login_required用于保护请求访问。 你需要发出一个请求来通过认证检查。
还会有很多从flask_login导入的current_user, 你的应用程序需要使用它们来让请求作为current_user的身份。
有两种方法可以使用flask_login实现以上功能。
  • 使用user_loader可以使请求对@login_required有效。 通常用于浏览器UI登录。 它将向浏览器存储会话cookie,并在以后使用它们进行身份验证。 所以你只需要登录一次,会话将保持一段时间。

  • 使用request_loader也可以与@login_required一起使用。 但它通常与api_key或基本身份验证一起使用。 例如,由其他应用程序与您的flask应用程序交互。 不会有会话cookie, 所以你每次发送请求时都需要提供认证信息。

有了user_loaderrequest_loader, 现在你有2种身份验证方式用于相同的api@login_required保护, 并且可使用current_user,非常聪明。

1
为了通过Angular验证Flask-Login的session_id以进行前端请求,您必须将withCredentials配置标志设置为true
也就是说,如果您正在使用Angular的$http.post(url,data [,config])或者$http.get(url [,config]),请确保config对象包含属性withCredentials且值为true。这将指示浏览器以与完整页面访问相同的方式使用其cookie。
例如:
$http.post('/api/login',{username:'myusername',password:'mypassword'},{withCredentials:true})

将数据{username:'myusername',password:'mypassword'}作为post请求提交到您的站点/应用程序的/api/login路由,如果使用Flask-Login并已登录,则Flask会知道。
您可以通过设置来为$http服务的所有请求设置此行为。
$httpProvider.defaults.withCredentials=true

在你的应用程序中的某个地方。目前,我将这行代码放在我的app.config块中,这似乎很合适:

var myApp = angular.module('myApp');

myApp.config(function ($httpProvider) {
  $httpProvider.defaults.withCredentials = true;
  });

(由于这篇文章涉及到 Flask,人们可能希望以某种方式通过 Angular 发送表单数据,使其可以在 request.form 中找到,这有一个类似的解决方案,供参考。)

嗨 Zach... 是的。当你有一个请求加载器时,这将起作用。但是,请注意,当你托管网站时,所有有权访问代码库的人都可以看到用户名和密码(基本上是全世界)...所以这可能会带来安全风险(可能)。 - galeej
嗨@galeej,你能再详细说明一下吗? 我承认我的例子非常奇怪 - 我展示了登录时传递凭证,这是仅有的不需要传递凭证的时候之一; 在此配置中由Angular发送的凭据仅为您的session_id,因为它由Flask-login格式化为cookie。 因此,在任意 $ http 调用中,实际上没有发送电子邮件和密码。 尽管如此,我仍然很好奇,为什么你认为任何可以访问“代码库”的人都可以访问任何用户信息,并且更进一步地,为什么“全世界”都会具有这种权限。 - Zach Siegel
我不知道我怎么错过了这个。我的意思是,当你在前端硬编码时,用户名和密码会被暴露出来(相比使用用户加载器)。如果你只是向客户使用API,则使用请求加载器。 - galeej
是的,谢谢!这就是它对我不起作用的原因!尽管我使用的是 React 而不是 Angular。 - Sebastian Nielsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接