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

2022-03-10 17:45 更新

該模塊包含各種第三方身份驗(yàn)證方案的實(shí)現(xiàn)。

此文件中的所有類都是類混合,旨在與 ?tornado.web.RequestHandler? 類一起使用。 它們以兩種方式使用:

在登錄處理程序上,使用 ?authenticate_redirect()?、?authorize_redirect()? 和 ?get_authenticated_user()? 等方法來(lái)建立用戶身份并將身份驗(yàn)證令牌存儲(chǔ)到您的數(shù)據(jù)庫(kù)或 cookie。

在非登錄處理程序中,使用 ?facebook_request()? 或 ?twitter_request()? 等方法使用身份驗(yàn)證令牌向相應(yīng)服務(wù)發(fā)出請(qǐng)求。

由于所有這些服務(wù)實(shí)現(xiàn)身份驗(yàn)證和授權(quán)的方式略有不同,因此它們的方法都略有不同。

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'})

通用協(xié)議

這些類實(shí)現(xiàn)了 OpenID 和 OAuth 標(biāo)準(zhǔn)。 通常需要對(duì)它們進(jìn)行子類化才能將它們用于任何特定站點(diǎn)。 所需的定制程度會(huì)有所不同,但在大多數(shù)情況下,覆蓋類屬性(由于歷史原因,這些屬性以下劃線開(kāi)頭)就足夠了。

class tornado.auth.OpenIdMixin

OpenID 和屬性交換的抽象實(shí)現(xiàn)。

類屬性:

?_OPENID_ENDPOINT?:提供身份的 URI。

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

重定向到此服務(wù)的身份驗(yàn)證 URL。

身份驗(yàn)證后,服務(wù)將重定向回給定的回調(diào) URI,并帶有其他參數(shù),包括 ?openid.mode?。

默認(rèn)情況下,我們?yōu)榻?jīng)過(guò)身份驗(yàn)證的用戶請(qǐng)求給定的屬性(姓名、電子郵件、語(yǔ)言和用戶名)。 如果您的應(yīng)用不需要所有這些屬性,則可以使用 ?ax_attrs關(guān)鍵字參數(shù)請(qǐng)求更少。

在 6.0 版更改: ?callback?參數(shù)已刪除,此方法不再返回可等待對(duì)象。 它現(xiàn)在是一個(gè)普通的同步函數(shù)。

get_auth_http_client() → tornado.httpclient.AsyncHTTPClient

返回要用于身份驗(yàn)證請(qǐng)求的 ?AsyncHTTPClient實(shí)例。

可以被子類覆蓋以使用默認(rèn)值以外的 HTTP 客戶端。

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

在重定向時(shí)獲取經(jīng)過(guò)身份驗(yàn)證的用戶數(shù)據(jù)。

這個(gè)方法應(yīng)該由從?authenticate_redirect()?方法接收重定向的處理程序調(diào)用(這通常與調(diào)用它的方法相同;在這種情況下,如果?openid.mode?參數(shù)存在則調(diào)用 ?get_authenticated_user?,如果不存在則調(diào)用 ?authenticate_redirect?。

這個(gè)方法的結(jié)果一般會(huì)被用來(lái)設(shè)置一個(gè)?cookie?。

在 6.0 版更改: ?callback?參數(shù)已刪除。 請(qǐng)改用返回的可等待對(duì)象。

class tornado.auth.OAuthMixin

OAuth 1.0 和 1.0a 的抽象實(shí)現(xiàn)。

類屬性:

  • ?_OAUTH_AUTHORIZE_URL?:服務(wù)的 OAuth 授權(quán) URL。
  • ?_OAUTH_ACCESS_TOKEN_URL?:服務(wù)的 OAuth 訪問(wèn)令牌 url。
  • ?_OAUTH_VERSION?:可以是“1.0”或“1.0a”。
  • ?_OAUTH_NO_CALLBACKS?:如果服務(wù)需要提前注冊(cè)回調(diào),則將此設(shè)置為 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

重定向用戶以獲取此服務(wù)的 OAuth 授權(quán)。

如果您之前已向第三方服務(wù)注冊(cè)了回調(diào) URI,則可以省略 ?callback_uri?。 對(duì)于某些服務(wù),您必須使用之前注冊(cè)的回調(diào) URI,并且不能通過(guò)此方法指定回調(diào)。

此方法設(shè)置一個(gè)名為 ?_oauth_request_token ?的 cookie,隨后出于安全目的在 ?get_authenticated_user中使用(并清除)該 cookie。

此方法是異步的,必須使用 ?await或 ?yield調(diào)用(這與此模塊中定義的其他 ?auth*_redirect? 方法不同)。 它會(huì)為您調(diào)用 ?RequestHandler.finish?,因此您不應(yīng)在它返回后編寫(xiě)任何其他響應(yīng)。

在 3.1 版更改: 現(xiàn)在返回一個(gè) ?Future并接受一個(gè)可選的回調(diào),以與 ?gen.coroutine? 兼容。

在 6.0 版更改: ?callback?參數(shù)已刪除。 請(qǐng)改用返回的可等待對(duì)象。

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

獲取 OAuth 授權(quán)用戶和訪問(wèn)令牌。

應(yīng)從 OAuth 回調(diào) URL 的處理程序調(diào)用此方法以完成注冊(cè)過(guò)程。 我們使用經(jīng)過(guò)身份驗(yàn)證的用戶字典運(yùn)行回調(diào)。 此字典將包含一個(gè) ?access_key?,可用于代表用戶向此服務(wù)發(fā)出授權(quán)請(qǐng)求。 字典還將包含其他字段,例如?name?,具體取決于所使用的服務(wù)。

在 6.0 版更改: ?callback?參數(shù)已刪除。 請(qǐng)改用返回的可等待對(duì)象。

_oauth_consumer_token() → Dict[str, Any]

子類必須覆蓋它以返回其 OAuth 使用者密鑰。

返回值應(yīng)該是帶有 ?key? 和 ?secret ?的字典。

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

子類必須覆蓋它以獲取有關(guān)用戶的基本信息。

應(yīng)該是一個(gè)協(xié)程,其結(jié)果是一個(gè)包含用戶信息的字典,可能已通過(guò)使用 ?access_token向服務(wù)發(fā)出請(qǐng)求來(lái)檢索。

訪問(wèn)令牌將添加到返回的字典中以生成 ?get_authenticated_user的結(jié)果。

在 5.1 版更改: 子類也可以使用 ?async def定義此方法。

在 6.0 版更改:刪除了對(duì) ?_oauth_get_user? 的同步回退。

get_auth_http_client() → tornado.httpclient.AsyncHTTPClient

返回要用于身份驗(yàn)證請(qǐng)求的 ?AsyncHTTPClient實(shí)例。

可以被子類覆蓋以使用默認(rèn)值以外的 HTTP 客戶端。

class tornado.auth.OAuth2Mixin

OAuth 2.0 的抽象實(shí)現(xiàn)。

類屬性:

  • ?_OAUTH_AUTHORIZE_URL?:服務(wù)的授權(quán) url。
  • ?_OAUTH_ACCESS_TOKEN_URL?:服務(wù)的訪問(wèn)令牌 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

重定向用戶以獲取此服務(wù)的 OAuth 授權(quán)。

一些提供商要求您在應(yīng)用程序中注冊(cè)一個(gè)重定向 URL,而不是通過(guò)此方法傳遞一個(gè)。 您應(yīng)該調(diào)用此方法使用戶登錄,然后在處理程序中為您的重定向 URL 調(diào)用 ?get_authenticated_user以完成授權(quán)過(guò)程。

在 6.0 版更改: ?callback?參數(shù)和?returned?的等待參數(shù)被刪除; 現(xiàn)在這是一個(gè)普通的同步函數(shù)。

get_auth_http_client() → tornado.httpclient.AsyncHTTPClient

返回要用于身份驗(yàn)證請(qǐng)求的 ?AsyncHTTPClient實(shí)例。

可以被子類覆蓋以使用默認(rèn)值以外的 HTTP 客戶端。

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

獲取給定的 URL 驗(yàn)證 OAuth2 訪問(wèn)令牌。

如果請(qǐng)求是 ?POST?,則應(yīng)提供 ?post_args?。 查詢字符串參數(shù)應(yīng)作為關(guān)鍵字參數(shù)給出。

示例:

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!")


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)