Skip to content

验证

¥Authentication

可以根据每个请求包含身份验证...

¥Authentication can either be included on a per-request basis...

>>> auth = httpx.BasicAuth(username="username", password="secret")
>>> client = httpx.Client()
>>> response = client.get("https://www.example.com/", auth=auth)

或者在客户端实例上配置,确保所有传出的请求都包含身份验证凭据......

¥Or configured on the client instance, ensuring that all outgoing requests will include authentication credentials...

>>> auth = httpx.BasicAuth(username="username", password="secret")
>>> client = httpx.Client(auth=auth)
>>> response = client.get("https://www.example.com/")

基本身份验证

¥Basic authentication

HTTP 基本身份验证是一种未加密的身份验证方案,它使用请求中的用户名和密码的简单编码Authorization标头。由于它是未加密的,因此通常只能用于https,尽管这并未得到严格执行。

¥HTTP basic authentication is an unencrypted authentication scheme that uses a simple encoding of the username and password in the request Authorization header. Since it is unencrypted it should typically only be used over https, although this is not strictly enforced.

>>> auth = httpx.BasicAuth(username="finley", password="secret")
>>> client = httpx.Client(auth=auth)
>>> response = client.get("https://httpbin.org/basic-auth/finley/secret")
>>> response
<Response [200 OK]>

摘要式身份验证

¥Digest authentication

HTTP 摘要式身份验证是一种质询-响应身份验证方案。与基本身份验证不同,它提供加​​密,并且可以在未加密的http连接。它需要额外的往返才能协商身份验证。

¥HTTP digest authentication is a challenge-response authentication scheme. Unlike basic authentication it provides encryption, and can be used over unencrypted http connections. It requires an additional round-trip in order to negotiate the authentication.

>>> auth = httpx.DigestAuth(username="olivia", password="secret")
>>> client = httpx.Client(auth=auth)
>>> response = client.get("https://httpbin.org/digest-auth/auth/olivia/secret")
>>> response
<Response [200 OK]>
>>> response.history
[<Response [401 UNAUTHORIZED]>]

NetRC 认证

¥NetRC authentication

HTTPX 可以配置为使用一个.netrc配置文件用于身份验证。

¥HTTPX can be configured to use a .netrc config file for authentication.

.netrcconfig 文件允许将身份验证凭据与指定的主机关联。当向 netrc 文件中找到的主机发出请求时,将使用 HTTP 基本身份验证包含用户名和密码。

¥The .netrc config file allows authentication credentials to be associated with specified hosts. When a request is made to a host that is found in the netrc file, the username and password will be included using HTTP basic authentication.

例子.netrc文件:

¥Example .netrc file:

machine example.org
login example-username
password example-password

machine python-httpx.org
login other-username
password other-password

一些配置示例.netrc身份验证httpx

¥Some examples of configuring .netrc authentication with httpx.

使用默认.netrc用户主目录中的文件:

¥Use the default .netrc file in the users home directory:

>>> auth = httpx.NetRCAuth()
>>> client = httpx.Client(auth=auth)

使用显式路径.netrc文件:

¥Use an explicit path to a .netrc file:

>>> auth = httpx.NetRCAuth(file="/path/to/.netrc")
>>> client = httpx.Client(auth=auth)

使用NETRC环境变量来配置路径.netrc文件,或者恢复为默认值。

¥Use the NETRC environment variable to configure a path to the .netrc file, or fallback to the default.

>>> auth = httpx.NetRCAuth(file=os.environ.get("NETRC"))
>>> client = httpx.Client(auth=auth)

NetRCAuth()类用途netrc.netrc()Python 标准库中的函数。有关以下情况可能引发的异常的详细信息,请参阅那里的文档.netrc未找到文件或无法解析。

¥The NetRCAuth() class uses the netrc.netrc() function from the Python standard library. See the documentation there for more details on exceptions that may be raised if the .netrc file is not found, or cannot be parsed.

自定义身份验证方案

¥Custom authentication schemes

当发出请求或实例化客户端时,auth参数可用于传递要使用的身份验证方案。auth参数可能是以下之一...

¥When issuing requests or instantiating a client, the auth argument can be used to pass an authentication scheme to use. The auth argument may be one of the following...

  • 二元组username/password,与基本身份验证一起使用。

    ¥A two-tuple of username/password, to be used with basic authentication.

  • 一个例子httpx.BasicAuth()httpx.DigestAuth(), 或者httpx.NetRCAuth()

    ¥An instance of httpx.BasicAuth(), httpx.DigestAuth(), or httpx.NetRCAuth().

  • 可调用,接受请求并返回经过身份验证的请求实例。

    ¥A callable, accepting a request and returning an authenticated request instance.

  • 子类的一个实例httpx.Auth

    ¥An instance of subclasses of httpx.Auth.

其中最复杂的是最后一个,它允许你创建涉及一个或多个请求的身份验证流程。httpx.Auth应该实施def auth_flow(request),并产生任何需要提出的请求......

¥The most involved of these is the last, which allows you to create authentication flows involving one or more requests. A subclass of httpx.Auth should implement def auth_flow(request), and yield any requests that need to be made...

class MyCustomAuth(httpx.Auth):
    def __init__(self, token):
        self.token = token

    def auth_flow(self, request):
        # Send the request, with a custom `X-Authentication` header.
        request.headers['X-Authentication'] = self.token
        yield request

如果授权流程需要多个请求,您可以发出多个收益,并在每种情况下获得响应...

¥If the auth flow requires more than one request, you can issue multiple yields, and obtain the response in each case...

class MyCustomAuth(httpx.Auth):
    def __init__(self, token):
        self.token = token

    def auth_flow(self, request):
      response = yield request
      if response.status_code == 401:
          # If the server issues a 401 response then resend the request,
          # with a custom `X-Authentication` header.
          request.headers['X-Authentication'] = self.token
          yield request

自定义身份验证类设计为不执行任何 I/O,因此它们可以用于同步和异步客户端实例。如果您正在实现需要请求主体的身份验证方案,则需要在类中使用requires_request_body财产。

¥Custom authentication classes are designed to not perform any I/O, so that they may be used with both sync and async client instances. If you are implementing an authentication scheme that requires the request body, then you need to indicate this on the class using a requires_request_body property.

然后您将能够访问request.content在里面.auth_flow()方法。

¥You will then be able to access request.content inside the .auth_flow() method.

class MyCustomAuth(httpx.Auth):
    requires_request_body = True

    def __init__(self, token):
        self.token = token

    def auth_flow(self, request):
      response = yield request
      if response.status_code == 401:
          # If the server issues a 401 response then resend the request,
          # with a custom `X-Authentication` header.
          request.headers['X-Authentication'] = self.sign_request(...)
          yield request

    def sign_request(self, request):
        # Create a request signature, based on `request.method`, `request.url`,
        # `request.headers`, and `request.content`.
        ...

类似地,如果您正在实施需要访问响应主体的方案,那么使用requires_response_body属性。然后您将能够访问响应主体属性和方法,例如response.contentresponse.textresponse.json(), ETC。

¥Similarly, if you are implementing a scheme that requires access to the response body, then use the requires_response_body property. You will then be able to access response body properties and methods such as response.content, response.text, response.json(), etc.

class MyCustomAuth(httpx.Auth):
    requires_response_body = True

    def __init__(self, access_token, refresh_token, refresh_url):
        self.access_token = access_token
        self.refresh_token = refresh_token
        self.refresh_url = refresh_url

    def auth_flow(self, request):
        request.headers["X-Authentication"] = self.access_token
        response = yield request

        if response.status_code == 401:
            # If the server issues a 401 response, then issue a request to
            # refresh tokens, and resend the request.
            refresh_response = yield self.build_refresh_request()
            self.update_tokens(refresh_response)

            request.headers["X-Authentication"] = self.access_token
            yield request

    def build_refresh_request(self):
        # Return an `httpx.Request` for refreshing tokens.
        ...

    def update_tokens(self, response):
        # Update the `.access_token` and `.refresh_token` tokens
        # based on a refresh response.
        data = response.json()
        ...

如果你需要执行 HTTP 请求以外的 I/O,例如访问基于磁盘的缓存,或者需要使用并发原语(例如锁),那么您应该重写.sync_auth_flow().async_auth_flow()(而不是.auth_flow())。前者将由httpx.Client,而后者将被使用httpx.AsyncClient

¥If you do need to perform I/O other than HTTP requests, such as accessing a disk-based cache, or you need to use concurrency primitives, such as locks, then you should override .sync_auth_flow() and .async_auth_flow() (instead of .auth_flow()). The former will be used by httpx.Client, while the latter will be used by httpx.AsyncClient.

import asyncio
import threading
import httpx


class MyCustomAuth(httpx.Auth):
    def __init__(self):
        self._sync_lock = threading.RLock()
        self._async_lock = asyncio.Lock()

    def sync_get_token(self):
        with self._sync_lock:
            ...

    def sync_auth_flow(self, request):
        token = self.sync_get_token()
        request.headers["Authorization"] = f"Token {token}"
        yield request

    async def async_get_token(self):
        async with self._async_lock:
            ...

    async def async_auth_flow(self, request):
        token = await self.async_get_token()
        request.headers["Authorization"] = f"Token {token}"
        yield request

如果你只想支持两种方法中的一种,那么你仍然应该覆盖它,但要提出一个明确的RuntimeError

¥If you only want to support one of the two methods, then you should still override it, but raise an explicit RuntimeError.

import httpx
import sync_only_library


class MyCustomAuth(httpx.Auth):
    def sync_auth_flow(self, request):
        token = sync_only_library.get_token(...)
        request.headers["Authorization"] = f"Token {token}"
        yield request

    async def async_auth_flow(self, request):
        raise RuntimeError("Cannot use a sync authentication class with httpx.AsyncClient")