我正在尝试使用 Tornado 框架构建一个网站,该框架使用 OpenID 对 OpenID 身份验证服务进行身份验证,该服务也是使用 Tornado 构建的。
我创建了一个基于 tornado.auth.OpenIdMixin 的子类,并将其用作我的 Tornado 应用程序中的身份验证处理程序:
class MyMixin(tornado.auth.OpenIdMixin):
_OPENID_ENDPOINT = "http://myserver.com/openidserver"
def authorize_redirect(self, oauth_scope, callback_uri=None, ax_attrs=["name", "email", "language", "username"]):
callback_uri = callback_uri or self.request.uri
args = self._openid_args(callback_uri, ax_attrs=ax_attrs)
self.redirect(self._OPENID_ENDPOINT + "?" + urllib_parse.urlencode(args))
def get_authenticated_user(self, callback):
tornado.auth.OpenIdMixin.get_authenticated_user(self, callback)
应用程序的处理程序类是
class AuthHandler(BaseHandler, MyMixin):
@tornado.web.asynchronous
def get(self):
if self.get_argument("openid.mode", None):
self.get_authenticated_user(self.async_callback(self._on_auth))
return
self.authenticate_redirect()
def _on_auth(self, user):
if not user:
self.send_error(500)
self.set_secure_cookie("user", tornado.escape.json_encode(user), expires_days=0.01)
self.redirect("/")
此代码基于 GoogleMixin 类正在执行的操作以及我在http://technobeans.wordpress.com/2012/09/04/tornado-third-party-authentication/上在线找到的示例
对于 OpenID 服务器,我从https://github.com/openid/python-openid的 server.py 开始,但在遇到一些问题后,我也尝试了https://github.com/mrjj/cito。在两台服务器中,我都有一个可供我登录的帐户,但两次我在客户端都遇到了同样的问题。
我的目标是让我的客户看到我没有登录,将我重定向到 OpenID 服务器,我在那里进行身份验证,授予客户端使用 ID 对我进行身份验证的权限,然后被重定向到客户端以从那里继续前进。
但是对于两台服务器,我的客户端总是在 AuthHandler._on_auth() 中失败,因为用户参数是 None。
这是运行我的客户端的 Tornado 的输出:
ERROR:root:Exception after headers written
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/tornado/web.py", line 897, in wrapper
return callback(*args, **kwargs)
File "website.py", line 67, in _on_auth
self.redirect("/")
File "/usr/lib/python2.7/dist-packages/tornado/web.py", line 412, in redirect
raise Exception("Cannot redirect after headers have been written")
Exception: Cannot redirect after headers have been written
添加一些调试print
语句后,我知道我得到的 HTTP/500 错误是因为user
变量为空。
我知道我不太了解 OpenID 应该如何工作,但我找不到 OpenID 应该如何工作的实际示例。有一些图表带有很多来回箭头,但没有更多的技术细节。
我看过的所有免费可用的服务器似乎都提供了相同的基本功能集。
- 我是否指向正确的 URL 以启动身份验证过程?
- 我是否在客户的 OpenID 处理过程中遗漏了一些步骤,并且它看起来太像 Google 使用他们的 OpenID+OAuth 协议所做的事情了?