Skip to main content

tornado.auth —使用OpenID和OAuth进行第三方登录

此模块包含各种第三方认证方案的实现。

此文件中的所有类都是旨在与 tornado.web.RequestHandler 类一起使用的类混合。它们以两种方式使用:

  • 在登录处理程序上,使用诸如 authenticate_redirect()authorize_redirect()get_authenticated_user() 之类的方法来建立用户的身份并将身份验证令牌存储到数据库和/或Cookie中。

  • 在非登录处理程序中,使用诸如 facebook_request()twitter_request() 的方法来使用认证令牌向相应的服务发出请求。

他们都采取稍微不同的参数,因为所有这些服务实现认证和授权稍有不同。有关完整的文档,请参阅下面的各个服务类。

Google OAuth的使用示例:

class GoogleOAuth2LoginHandler(tornado.web.RequestHandler,
                               tornado.auth.GoogleOAuth2Mixin):
    @tornado.gen.coroutine
    def get(self):
        if self.get_argument('code', False):
            user = yield self.get_authenticated_user(
                redirect_uri='http://your.site.com/auth/google',
                code=self.get_argument('code'))
            # Save the user with e.g. set_secure_cookie
        else:
            yield self.authorize_redirect(
                redirect_uri='http://your.site.com/auth/google',
                client_id=self.settings['google_oauth']['key'],
                scope=['profile', 'email'],
                response_type='code',
                extra_params={'approval_prompt': 'auto'})

在 4.0 版更改: 此模块中的所有回调接口现在保证运行他们的回调与 None 的参数时出错。以前,一些函数会这样做,而其他函数会自行终止请求。此更改还确保通过 Future 接口更一致地报告错误。

公共协议

这些类实现OpenID和OAuth标准。他们通常需要被子类化以使用它们与任何特定的网站。所需的定制程度会有所不同,但在大多数情况下,超过类属性(由于历史原因以下划线开头)就足够了。

class tornado.auth.OpenIdMixin[源代码]

OpenID和属性交换的抽象实现。

类属性:

  • _OPENID_ENDPOINT:身份提供者的URI。

authenticate_redirect(*args, **kwargs)[源代码]

重定向到此服务的身份验证URL。

认证后,服务将重定向回给定的回调URI与附加参数,包括 openid.mode

默认情况下,我们请求经过身份验证的用户的给定属性(名称,电子邮件,语言和用户名)。如果您不需要应用程序的所有这些属性,可以使用ax_attrs关键字参数请求较少的属性。

在 3.1 版更改: 返回 Future 并接受可选的回调。这些不是严格必需的,因为这种方法是同步的,但是它们被提供以与 OAuthMixin.authorize_redirect 一致。

get_authenticated_user(*args, **kwargs)[源代码]

在重定向上获取经过身份验证的用户数据。

这个方法应该被处理程序调用,该处理程序从 authenticate_redirect() 方法接收重定向(这通常与调用它的方法相同;在这种情况下,如果 openid.mode 参数存在,则调用 get_authenticated_user,否则调用 authenticate_redirect)。

此方法的结果通常用于设置cookie。

get_auth_http_client()[源代码]

返回要用于身份验证请求的 AsyncHTTPClient 实例。

可能被子类覆盖以使用默认值以外的HTTP客户端。

class tornado.auth.OAuthMixin[源代码]

OAuth 1.0和1.0a的抽象实现。

有关示例实现,请参阅下面的 TwitterMixin

类属性:

  • _OAUTH_AUTHORIZE_URL:服务的OAuth授权网址。

  • _OAUTH_ACCESS_TOKEN_URL:服务的OAuth访问令牌网址。

  • _OAUTH_VERSION:可以是“1.0”或“1.0a”。

  • _OAUTH_NO_CALLBACKS:如果服务需要预先注册回调,请将此设置为True。

子类还必须覆盖 _oauth_get_user_future_oauth_consumer_token 方法。

authorize_redirect(*args, **kwargs)[源代码]

重定向用户以获取此服务的OAuth授权。

如果您之前已经使用第三方服务注册了回调URI,则可以省略 callback_uri。对于某些服务(包括Friendfeed),您必须使用先前注册的回调URI,并且不能通过此方法指定回调。

此方法设置一个名为 _oauth_request_token 的cookie,为了安全起见,随后在 get_authenticated_user 中使用(并清除)该cookie。

注意这个方法是异步的,虽然它为你调用 RequestHandler.finish,所以它可能没有必要传递一个回调或使用 Future 它返回。但是,如果从用 gen.coroutine 装饰的函数调用此方法,则必须使用 yield 调用此方法,以防止过早关闭响应。

在 3.1 版更改: 现在返回 Future,并采用可选的回调,以与 gen.coroutine 兼容。

get_authenticated_user(*args, **kwargs)[源代码]

获取OAuth授权的用户和访问令牌。

应该从OAuth回调URL的处理程序调用此方法以完成注册过程。我们使用经过身份验证的用户字典运行回调。此字典将包含一个 access_key,可用于代表用户对此服务进行授权的请求。字典还将包含其他字段,例如 name,具体取决于使用的服务。

_oauth_consumer_token()[源代码]

子类必须覆盖此值才能返回其OAuth使用方键值。

返回值应该是具有密钥 keysecretdict

_oauth_get_user_future(*args, **kwargs)[源代码]

子类必须覆盖此,以获取有关用户的基本信息。

应返回一个 Future,其结果是包含有关该用户的信息的字典,该字典可能已通过使用 access_token 检索到向服务发出请求。

访问令牌将被添加到返回的字典中以生成 get_authenticated_user 的结果。

为了向后兼容,还支持基于回调的 _oauth_get_user 方法。

get_auth_http_client()[源代码]

返回要用于身份验证请求的 AsyncHTTPClient 实例。

可能被子类覆盖以使用默认值以外的HTTP客户端。

class tornado.auth.OAuth2Mixin[源代码]

OAuth 2.0的抽象实现。

有关示例实现,请参阅下面的 FacebookGraphMixinGoogleOAuth2Mixin

类属性:

  • _OAUTH_AUTHORIZE_URL:服务的授权网址。

  • _OAUTH_ACCESS_TOKEN_URL:服务的访问令牌网址。

authorize_redirect(*args, **kwargs)[源代码]

重定向用户以获取此服务的OAuth授权。

某些提供商要求您使用应用程序注册重定向网址,而不是通过此方法传递。您应该调用此方法将用户登录,然后在重定向URL的处理程序中调用 get_authenticated_user 以完成授权过程。

在 3.1 版更改: 返回 Future 并接受可选的回调。这些不是严格必需的,因为这种方法是同步的,但是它们被提供以与 OAuthMixin.authorize_redirect 一致。

oauth2_request(*args, **kwargs)[源代码]

获取给定的网址授权OAuth2访问令牌。

如果请求是POST,则应提供 post_args。查询字符串参数应作为关键字参数。

用法示例:

..testcode:

class MainHandler(tornado.web.RequestHandler,
                  tornado.auth.FacebookGraphMixin):
    @tornado.web.authenticated
    @tornado.gen.coroutine
    def get(self):
        new_entry = yield self.oauth2_request(
            "https://graph.facebook.com/me/feed",
            post_args={"message": "I am posting from my Tornado application!"},
            access_token=self.current_user["access_token"])

        if not new_entry:
            # Call failed; perhaps missing permission?
            yield self.authorize_redirect()
            return
        self.finish("Posted a message!")

4.3 新版功能.

get_auth_http_client()[源代码]

返回要用于身份验证请求的 AsyncHTTPClient 实例。

可能被子类覆盖以使用默认值以外的HTTP客户端。

4.3 新版功能.

谷歌

class tornado.auth.GoogleOAuth2Mixin[源代码]

使用OAuth2的Google身份验证。

要使用,请向Google注册您的应用程序,并将相关参数复制到应用程序设置。

  • 前往 http://console.developers.google.com 的Google开发人员控制台

  • 选择一个项目,或创建一个新项目。

  • 在左侧的边栏中,选择API和验证。

  • 在API列表中,找到Google+ API服务并将其设置为开启。

  • 在左侧的边栏中,选择凭据。

  • 在页面的OAuth部分中,选择创建新客户端ID。

  • 将重定向URI设置为指向您的授权处理程序

  • 将“客户端密钥”和“客户端ID”复制为应用设置{“google_oauth”:{“key”:CLIENT_ID,“secret”:CLIENT_SECRET}}

3.2 新版功能.

get_authenticated_user(*args, **kwargs)[源代码]

处理Google用户的登录信息,返回访问令牌。

结果是包含 access_token 字段([其他](https://developers.google.com/identity/protocols/OAuth2WebServer#handlingtheresponse))的字典。与此包中的其他 get_authenticated_user 方法不同,此方法不返回有关用户的任何其他信息。返回的访问令牌可以与 OAuth2Mixin.oauth2_request 一起使用以请求附加信息(可能来自 https://www.googleapis.com/oauth2/v2/userinfo

用法示例:

class GoogleOAuth2LoginHandler(tornado.web.RequestHandler,
                               tornado.auth.GoogleOAuth2Mixin):
    @tornado.gen.coroutine
    def get(self):
        if self.get_argument('code', False):
            access = yield self.get_authenticated_user(
                redirect_uri='http://your.site.com/auth/google',
                code=self.get_argument('code'))
            user = yield self.oauth2_request(
                "https://www.googleapis.com/oauth2/v1/userinfo",
                access_token=access["access_token"])
            # Save the user and access token with
            # e.g. set_secure_cookie.
        else:
            yield self.authorize_redirect(
                redirect_uri='http://your.site.com/auth/google',
                client_id=self.settings['google_oauth']['key'],
                scope=['profile', 'email'],
                response_type='code',
                extra_params={'approval_prompt': 'auto'})

Facebook

class tornado.auth.FacebookGraphMixin[源代码]

使用新的Graph API和OAuth2的Facebook身份验证。

get_authenticated_user(*args, **kwargs)[源代码]

处理Facebook用户的登录,返回一个用户对象。

用法示例:

class FacebookGraphLoginHandler(tornado.web.RequestHandler,
                                tornado.auth.FacebookGraphMixin):
  @tornado.gen.coroutine
  def get(self):
      if self.get_argument("code", False):
          user = yield self.get_authenticated_user(
              redirect_uri='/auth/facebookgraph/',
              client_id=self.settings["facebook_api_key"],
              client_secret=self.settings["facebook_secret"],
              code=self.get_argument("code"))
          # Save the user with e.g. set_secure_cookie
      else:
          yield self.authorize_redirect(
              redirect_uri='/auth/facebookgraph/',
              client_id=self.settings["facebook_api_key"],
              extra_params={"scope": "read_stream,offline_access"})
facebook_request(*args, **kwargs)[源代码]

获取给定的相对API路径,例如“/btaylor/picture”

如果请求是POST,则应提供 post_args。查询字符串参数应作为关键字参数。

关于Facebook Graph API的介绍可以在 http://developers.facebook.com/docs/api 找到

许多方法需要OAuth访问令牌,您可以通过 authorize_redirectget_authenticated_user 获取。通过该过程返回的用户包括可用于通过此方法进行验证请求的 access_token 属性。

用法示例:

..testcode:

class MainHandler(tornado.web.RequestHandler,
                  tornado.auth.FacebookGraphMixin):
    @tornado.web.authenticated
    @tornado.gen.coroutine
    def get(self):
        new_entry = yield self.facebook_request(
            "/me/feed",
            post_args={"message": "I am posting from my Tornado application!"},
            access_token=self.current_user["access_token"])

        if not new_entry:
            # Call failed; perhaps missing permission?
            yield self.authorize_redirect()
            return
        self.finish("Posted a message!")

给定的路径相对于 self._FACEBOOK_BASE_URL,默认为“ https://graph.facebook.com ”。

这个方法是 OAuth2Mixin.oauth2_request 的一个包装;唯一的区别是这个方法需要一个相对路径,而 oauth2_request 需要一个完整的url。

在 3.1 版更改: 添加了覆盖 self._FACEBOOK_BASE_URL 的能力。

推特

class tornado.auth.TwitterMixin[源代码]

Twitter OAuth身份验证。

要使用Twitter进行身份验证,请在 http://twitter.com/apps 使用Twitter注册您的应用程序。然后将您的客户密钥和使用方密钥复制到应用程序 settings twitter_consumer_keytwitter_consumer_secret。在您注册为应用程序的回调URL的URL的处理程序上使用此mixin。

当您的应用程序设置时,您可以使用此混合使用Twitter验证用户,并获得访问他们的流:

class TwitterLoginHandler(tornado.web.RequestHandler,
                          tornado.auth.TwitterMixin):
    @tornado.gen.coroutine
    def get(self):
        if self.get_argument("oauth_token", None):
            user = yield self.get_authenticated_user()
            # Save the user using e.g. set_secure_cookie()
        else:
            yield self.authorize_redirect()

get_authenticated_user 返回的用户对象包括属性 usernamenameaccess_tokenhttps://dev.twitter.com/docs/api/1.1/get/users/show 中描述的所有自定义Twitter用户属性

authenticate_redirect(*args, **kwargs)[源代码]

就像 authorize_redirect,但自动重定向,如果授权。

如果您使用Twitter进行单点登录,这通常是正确的界面。

在 3.1 版更改: 现在返回 Future,并采用可选的回调,以与 gen.coroutine 兼容。

twitter_request(*args, **kwargs)[源代码]

获取给定的API路径,例如 statuses/user_timeline/btaylor

路径不应包含格式或API版本号。 (我们自动使用JSON格式和API版本1)。

如果请求是POST,则应提供 post_args。查询字符串参数应作为关键字参数。

所有的Twitter方法都记录在 http://dev.twitter.com/

许多方法需要OAuth访问令牌,您可以通过 authorize_redirectget_authenticated_user 获取。通过该过程返回的用户包括一个“access_token”属性,可用于通过此方法进行身份验证请求。用法示例:

class MainHandler(tornado.web.RequestHandler,
                  tornado.auth.TwitterMixin):
    @tornado.web.authenticated
    @tornado.gen.coroutine
    def get(self):
        new_entry = yield self.twitter_request(
            "/statuses/update",
            post_args={"status": "Testing Tornado Web Server"},
            access_token=self.current_user["access_token"])
        if not new_entry:
            # Call failed; perhaps missing permission?
            yield self.authorize_redirect()
            return
        self.finish("Posted a message!")