我有一个Python Flask-Login网络应用程序,可以在Web浏览器中正常运行。 这是我的用户对象:
class User():
def __init__(self, user, password_hash):
self.user = user
self.password = password_hash
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return unicode(self.user)
def get_auth_token(self, user, password):
data = [str(self.user), self.password]
return serializer.dumps(data, salt=serializer_secret)
我像这样登录用户(当然是在正常的用户名/密码检查之后):
user_object = User(user, password_hash)
result = login_user(user_object)
在应用程序的后续部分中,我得到了用户的ID:
user = current_user.get_id()
Web应用程序用户登录功能始终如一。 我正在尝试使用NSURLSession:
在Swift 2中创建一个iOS9应用程序func HTTPsendRequest(request:NSMutableURLRequest, fireCallback:(String, Int, AnyObject?) -> Void) {
let task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { data, response, error in
let httpStatusCode:Int
if error != nil {
if let httpResponse = response as? NSHTTPURLResponse {
httpStatusCode = httpResponse.statusCode
fireCallback("", httpStatusCode, (error!.localizedDescription) as String)
}
} else {
let result = NSString(data:data!, encoding:NSASCIIStringEncoding)!
if let httpResponse = response as? NSHTTPURLResponse {
httpStatusCode = httpResponse.statusCode
fireCallback(result as String, httpStatusCode, nil)
}
}
})
task.resume()
}
func HTTPPost(url:String, data:String, callback:(String, Int, AnyObject?) -> Void) {
let url = NSURL(string:url)!
let request = NSMutableURLRequest(URL:url)
let data: NSData = data.dataUsingEncoding(NSUTF8StringEncoding)!
request.HTTPBody = data
request.HTTPMethod = "POST"
request.addValue("application/json", forHTTPHeaderField:"Content-Type")
request.addValue("text/plain", forHTTPHeaderField:"Accept")
HTTPsendRequest(request, fireCallback:callback)
}
dispatch_async(dispatch_get_main_queue()) {
HTTPPost("\(apiUrl)login", data:JSONPayload) { (response: String, httpStatusCode: Int, error: AnyObject?) -> Void in
token = response
}
}
此登录功能由于某种原因间歇性地不记录用户。我没有做任何不同的事情,只是反复单击应用程序上的“登录”按钮,该按钮将电子邮件和密码哈希发送到API端点。有时候它有效,有时则不然。根据Flask-Login文档:
默认情况下,当用户实际未登录时, current_user设置为AnonymousUserMixin对象。它有 以下属性和方法:
is_active和is_authenticated是False is_anonymous是True get_id() 返回无
在尝试从Swift iOS应用程序登录后,get_id()
会间歇性地返回None
,我无法弄清楚原因,这让我疯狂。
我已经尝试确保使用相同的线程登录然后使用响应。我已确保在使用信号量和串行队列或仅使用dispatch_get_main_queue()
异步触发需要登录响应的任何未来调用之前返回登录响应。
有没有人遇到过这个?救命啊!
----------------------------------- EDIT ----------- -----------------------
我已经运行测试并确认在swift ios应用程序的每次错误登录尝试中,烧瓶应用程序都会返回login_user(user_object)的这些值:
current_user.is_authenticated() => True
current_user.is_active() => True
current_user.is_anonymous() => False
current_user.get_id() = <user's id>
因此用户始终正确登录。
但是在随后的调用中,直接在登录后,到另一个需要用户登录的功能,就是错误所在。
这个其他函数用@login_required
装饰器修饰。
如果此测试失败,则应返回401 Not Authorized,它在实际情况下会返回。但由于某种原因,当用户刚刚登录时有时会返回500,当它发生时,在日志文件中我可以看到例外情况:
File "/usr/local/lib/python2.7/site-packages/flask_login.py", line 756, in decorated_view
elif not current_user.is_authenticated():
File "/usr/local/lib/python2.7/site-packages/flask_login.py", line 794, in _get_user
current_app.login_manager._load_user()
File "/usr/local/lib/python2.7/site-packages/flask_login.py", line 363, in _load_user
return self.reload_user()
File "/usr/local/lib/python2.7/site-packages/flask_login.py", line 325, in reload_user
user = self.user_callback(user_id)
TypeError: 'NoneType' object is not callable
所以问题现在变成了,如果用户已经成功登录,为什么login_required
无法从用户对象中找到用户呢?