阅读(3317) (0)

Tornado 使用OpenID 和 OAuth的第三方登录

2022-03-10 17:09:46 更新

该模块包含各种第三方身份验证方案的实现。

此文件中的所有类都是类混合,旨在与 ​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):
    async def get(self):
        if self.get_argument('code', False):
            user = await 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:
            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'})

通用协议

这些类实现了 OpenID 和 OAuth 标准。 通常需要对它们进行子类化才能将它们用于任何特定站点。 所需的定制程度会有所不同,但在大多数情况下,覆盖类属性(由于历史原因,这些属性以下划线开头)就足够了。

class tornado.auth.OpenIdMixin

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

类属性:

_OPENID_ENDPOINT​:提供身份的 URI。

authenticate_redirect(callback_uri: Optional[str] = None, ax_attrs: List[str] = ['name', 'email', 'language', 'username']) → None

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

身份验证后,服务将重定向回给定的回调 URI,并带有其他参数,包括 ​openid.mode​。

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

在 6.0 版更改: ​callback​参数已删除,此方法不再返回可等待对象。 它现在是一个普通的同步函数。

get_auth_http_client() → tornado.httpclient.AsyncHTTPClient

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

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

coroutineget_authenticated_user(http_client: Optional[tornado.httpclient.AsyncHTTPClient] = None) → Dict[str, Any]

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

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

这个方法的结果一般会被用来设置一个​cookie​。

在 6.0 版更改: ​callback​参数已删除。 请改用返回的可等待对象。

class tornado.auth.OAuthMixin

OAuth 1.0 和 1.0a 的抽象实现。

类属性:

  • _OAUTH_AUTHORIZE_URL​:服务的 OAuth 授权 URL。
  • _OAUTH_ACCESS_TOKEN_URL​:服务的 OAuth 访问令牌 url。
  • _OAUTH_VERSION​:可以是“1.0”或“1.0a”。
  • _OAUTH_NO_CALLBACKS​:如果服务需要提前注册回调,则将此设置为 True。

子类还必须覆盖 ​_oauth_get_user_future ​和 ​_oauth_consumer_token方法。

authorize_redirect(callback_uri: Optional[str] = None, extra_params: Optional[Dict[str, Any]] = None, http_client: Optional[tornado.httpclient.AsyncHTTPClient] = None) → None

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

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

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

此方法是异步的,必须使用 ​await或 ​yield调用(这与此模块中定义的其他 ​auth*_redirect​ 方法不同)。 它会为您调用 ​RequestHandler.finish​,因此您不应在它返回后编写任何其他响应。

在 3.1 版更改: 现在返回一个 ​Future并接受一个可选的回调,以与 ​gen.coroutine​ 兼容。

在 6.0 版更改: ​callback​参数已删除。 请改用返回的可等待对象。

get_authenticated_user(http_client: Optional[tornado.httpclient.AsyncHTTPClient] = None) → Dict[str, Any]

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

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

在 6.0 版更改: ​callback​参数已删除。 请改用返回的可等待对象。

_oauth_consumer_token() → Dict[str, Any]

子类必须覆盖它以返回其 OAuth 使用者密钥。

返回值应该是带有 ​key​ 和 ​secret ​的字典。

_oauth_get_user_future(access_token: Dict[str, Any]) → Dict[str, Any]

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

应该是一个协程,其结果是一个包含用户信息的字典,可能已通过使用 ​access_token向服务发出请求来检索。

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

在 5.1 版更改: 子类也可以使用 ​async def定义此方法。

在 6.0 版更改:删除了对 ​_oauth_get_user​ 的同步回退。

get_auth_http_client() → tornado.httpclient.AsyncHTTPClient

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

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

class tornado.auth.OAuth2Mixin

OAuth 2.0 的抽象实现。

类属性:

  • _OAUTH_AUTHORIZE_URL​:服务的授权 url。
  • _OAUTH_ACCESS_TOKEN_URL​:服务的访问令牌 url。

authorize_redirect(redirect_uri: Optional[str] = None, client_id: Optional[str] = None, client_secret: Optional[str] = None, extra_params: Optional[Dict[str, Any]] = None, scope: Optional[List[str]] = None, response_type: str = 'code') → None

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

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

在 6.0 版更改: ​callback​参数和​returned​的等待参数被删除; 现在这是一个普通的同步函数。

get_auth_http_client() → tornado.httpclient.AsyncHTTPClient

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

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

coroutine oauth2_request(url: str, access_token: Optional[str] = None, post_args: Optional[Dict[str, Any]] = None, **args) → Any

获取给定的 URL 验证 OAuth2 访问令牌。

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

示例:

class MainHandler(tornado.web.RequestHandler,
                  tornado.auth.FacebookGraphMixin):
    @tornado.web.authenticated
    async def get(self):
        new_entry = await 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?
            self.authorize_redirect()
            return
        self.finish("Posted a message!")