flask 检验是否已经登录的代码,为什么写在函数内部一切正常,用装饰器后出错?

2016-02-18 21:39:59 +08:00
 fatea
https://gist.github.com/fatea/ce2265ae6bef4e6691a2
请问这是为什么呢?
6439 次点击
所在节点    Python
13 条回复
Kilerd
2016-02-18 21:55:17 +08:00
1. current_user 默认都不是 None
2. is_authenticated => is_authenticated() 这是一个函数。

至于你说的 问题, 草草看一眼没看出来
fatea
2016-02-18 22:44:48 +08:00
@Kilerd 1. 谢谢~ 2.在最新的 flask_login 里, is_authenticated 已经变成了 bool 了。
问题很奇怪,而且估计不是 装饰器的问题,哪怕在函数内部,也要先判断 flask.request.method ,否则还是一样的错误
mianju
2016-02-18 22:54:16 +08:00
使用 flask-login 这个了么?
Kilerd
2016-02-18 23:06:30 +08:00
@fatea flask-login 不是自带登陆检测装饰器吗?

from flask_login import login_required


以下是他的代码:
''' python
def login_required(func):
'''
If you decorate a view with this, it will ensure that the current user is
logged in and authenticated before calling the actual view. (If they are
not, it calls the :attr:`LoginManager.unauthorized` callback.) For
example::

@app.route('/post')
@login_required
def post():
pass

If there are only certain times you need to require that your user is
logged in, you can do so with::

if not current_user.is_authenticated:
return current_app.login_manager.unauthorized()

...which is essentially the code that this function adds to your views.

It can be convenient to globally turn off authentication when unit testing.
To enable this, if the application configuration variable `LOGIN_DISABLED`
is set to `True`, this decorator will be ignored.

:param func: The view function to decorate.
:type func: function
'''
@wraps(func)
def decorated_view(*args, **kwargs):
if current_app.login_manager._login_disabled:
return func(*args, **kwargs)
elif not current_user.is_authenticated:
return current_app.login_manager.unauthorized()
return func(*args, **kwargs)
return decorated_view
'''


BTW , is_authenticated 只是你的用户 ORM 模型里面的一个函数,用来验证是否用户通过验证罢了,并不是 boolean

` current_user = LocalProxy(lambda: _get_user()) `

根据你的设置,只想到你的用户 ORM 模型

所以 ` current_user.is_authenticated ` 就应该是自己设置的。 当然如果你不需要用到这个字段,设置成 boolean 或者 True 也是可以得。

未登录的使用 可以用

`if not current_user.is_authenticated(): pass `
Kilerd
2016-02-18 23:07:29 +08:00
上面的代码看不清楚,请移至 markdown 编辑器中查看,懒得用 gist 了
fatea
2016-02-18 23:27:10 +08:00
@Kilerd 嗯...我需要的 是 "未登录状态的检测", login_required 肯定不是用在这儿的嘛。
对于另一个问题, Since 0.3.0, Flask-Login has set is_active, is_authenticated, is_anonymous to property in UserMixin 。可以看到你贴出来的代码里也是`if not current_user.is_authenticated:`

抛开上面的细节... 其实最后的问题就是:

为什么 if current_user.is_authenticated: 不能在函数的入口处使用,而只能在 request.method == 'GET'之后使用?

补充下:刚才发现,在 request.method == 'POST'情况下, if current_user.is_authenticated 还是会出一样的错。

然后我在多处打 log(Node.js 的习惯...console.log()),发现了原因:

在刚接受到 POST 请求, current_user.is_authenticated 就 为 True ,所以根本没有执行之后的登录就返回了。
fatea
2016-02-18 23:27:51 +08:00
@Kilerd 虽然发现了原因...但是并不明白为什么 T_T
Kilerd
2016-02-18 23:35:29 +08:00
@fatea 未登录的可以自己写一个装饰器啊。

def require_not_login(func):
@wraps(func)
----def decorated_view(*args, **kwargs):
--------if not current_user.is_authenticated():
------------return func(*args, **kwargs)
--------else:
------------flash(_"you must log out before doing this.", "error")
------------return redirect(url_for("..."))
fatea
2016-02-18 23:37:17 +08:00
@Kilerd 这样写报错了所以我来求助的嘛.... 一言以蔽之,就是不能让 if not current_user.is_authenticated 处理 POST 请求,否则出错。
Kilerd
2016-02-18 23:39:36 +08:00
把你的 用户模型 和 关于 flask_login 的代码贴出来。
fatea
2016-02-18 23:47:08 +08:00
fatea
2016-02-19 00:01:40 +08:00
@Kilerd 那个 login_manager.request_loader 在这里应该没有用吧?因为我判断登录都是 session 来的,而且 log 表示也没有用到它
fatea
2016-02-19 00:15:01 +08:00
@Kilerd 我解决了。。。的确是 login_manager.request_loader 的原因,所有的 request 都会经过它,导致的错误,把它注释掉就正常了,装饰器什么的也正常不受影响。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/257484

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX