首页 / 资讯中心 / 文章详情

基于 Authlib 在 Django 中构建 OAuth 1.0 授权服务器与资源服务器

基于 Authlib 在 Django 中构建 OAuth 1.0 授权服务器与资源服务器 ★ FEATURED ARTICLE
【免费下载链接】authlibThe ultimate Python library in building OAuth, OpenID Connect clients and servers. JWS, JWE, JWK, JWA, JWT included.项目地址https://gitcode.com/gh_mirrors/au/authlib点击查看免费下载本指南完整讲解如何使用 Authlib 的authlib.integrations.django_oauth1集成在 Django 项目中搭建一个 OAuth 1.0 Provider——包括负责签发令牌的Authorization Server授权服务器与负责校验访问令牌的Resources Server资源服务器。读完本文你将掌握从数据模型设计、三个核心端点实现、签名与防重放校验到资源接口鉴权保护的完整实战方案。OAuth 1.0 Provider 的两大组成按照 docs/oauth1/concepts.rst 对 OAuth 1.0 的说明一个 Provider 由两类服务器组成Authorization Server负责发放访问令牌。它对外提供临时凭证temporary credentials、资源所有者授权authorization与令牌凭证token credentials签发等端点Resources Server负责守护用户的受保护资源只允许持有合法授权访问令牌的客户端访问。在当前仓库中Django 的 OAuth 1.0 Provider 实现位于 authlib/integrations/django_oauth1/ 目录对外导出BaseServer、CacheAuthorizationServer与ResourceProtector三个类见init.py。需要提醒的是官方文档明确指出这是Django OAuth 1.0 Provider 的 alpha 实现功能上以可用、可扩展为主。一个完整的 OAuth 1.0 授权流程通常包括六个步骤客户端用自身凭证向服务器请求临时凭证服务器校验客户端凭证后返回临时凭证客户端保存临时凭证并引导资源所有者打开浏览器完成授权资源所有者授权成功后服务器返回verifier授权码客户端用 verifier 与临时凭证换取令牌凭证服务器校验全部信息后发放访问令牌客户端此后即可携带令牌访问受保护资源。本地开发的必要准备AUTHLIB_INSECURE_TRANSPORTOAuth 1.0 规范要求请求必须通过 HTTPS 安全通道传输InsecureTransportError的说明见 errors.py。因此在本地localhost开发时务必先设置环境变量export AUTHLIB_INSECURE_TRANSPORTtrue该环境变量在 authlib/common/security.py 的is_secure_transport()中被读取只要设置了它即视为安全传输否则仅当 URL 为https、主机名为localhost或回环地址loopback时才判定为安全。测试代码 tests/django/test_oauth1/conftest.py 也通过该环境变量来让用例跑通。生产环境务必关闭此开关并确保站点启用 HTTPS。最小可运行配置CacheAuthorizationServerAuthlib 的 Django 集成大量使用 Django 缓存机制django.core.cache因此临时凭证、时间戳与 nonce 的存储校验全部内置你无需自己实现这些细节。创建授权服务器只需要Client与Token两个模型from your_project.models import Client, Token from authlib.integrations.django_oauth1 import CacheAuthorizationServer authorization_server CacheAuthorizationServer(Client, Token)从源码 authorization_server.py 可以看到CacheAuthorizationServer的内部机制create_temporary_credential()把临时凭证以temporary_credential:{oauth_token}为键写入 Django 缓存同时记录client_id与oauth_callbackget_temporary_credential()/delete_temporary_credential()按令牌键从缓存读取或删除临时凭证create_authorization_verifier()授权通过后生成 36 位oauth_verifier并把user_id一并写入缓存供后续换发令牌时使用。这样临时凭证的生命周期完全由缓存过期时间控制令牌凭证则要求持久化到数据库见下文 Token 模型。定义 Django 数据模型Resource Owner资源所有者资源所有者就是使用你服务的用户。他可以用用户名/邮箱加密码等方式登录你的网站。Django 场景下直接使用内置的 contrib 用户模型即可from django.contrib.auth.models import UserClient 模型Client 是代表资源所有者发起受保护资源请求的第三方应用至少包含三部分信息Client Identifier即client_idClient Password即client_secretClient RSA Public Key若支持 RSA-SHA1 签名方法时提供。Authlib 没有为 Django 提供现成的 Client 模型需要自己实现。只需继承authlib.oauth1.ClientMixin并实现其抽象方法from django.db import models from django.contrib.auth.models import User from authlib.oauth1 import ClientMixin class Client(models.Model, ClientMixin): user models.ForeignKey(User, on_deleteCASCADE) client_id models.CharField(max_length48, uniqueTrue, db_indexTrue) client_secret models.CharField(max_length48, blankTrue) default_redirect_uri models.TextField(blankFalse, default) def get_default_redirect_uri(self): return self.default_redirect_uri def get_client_secret(self): return self.client_secret def get_rsa_public_key(self): return NoneClientMixin在 authlib/oauth1/rfc5849/models.py 中定义包含get_default_redirect_uri()、get_client_secret()、get_rsa_public_key()三个必须实现的方法。Client 通常由开发者用户在你的网站上注册获得。仓库测试中的 Client 模型实现见 tests/django/test_oauth1/models.py。Token 模型令牌凭证token credential用于访问资源所有者的资源。与 OAuth 2 不同OAuth 1.0 的令牌凭证不会过期因此应保存到持久化数据库中而非缓存。示例实现from django.db import models from django.contrib.auth.models import User from authlib.oauth1 import TokenCredentialMixin class Token(models.Model, TokenCredentialMixin): user models.ForeignKey(User, on_deleteCASCADE) client_id models.CharField(max_length48, db_indexTrue) oauth_token models.CharField(max_length84, uniqueTrue, db_indexTrue) oauth_token_secret models.CharField(max_length84) def get_oauth_token(self): return self.oauth_token def get_oauth_token_secret(self): return self.oauth_token_secretTokenCredentialMixinmodels.py要求实现get_oauth_token()与get_oauth_token_secret()。令牌的生成由服务器默认的token_generator完成——见 authorization_server.py它会生成 42 位的oauth_token与 48 位的oauth_token_secret基于authlib.common.security.generate_token。你也可以在构造CacheAuthorizationServer时传入自定义的token_generator覆盖默认行为。实现授权服务器的三个核心端点1. 临时凭证端点Temporary Credential Endpoint该端点供客户端获取临时凭证必须限定为 POST 方法from django.views.decorators.http import require_http_methods require_http_methods([POST]) def initiate_temporary_credential(request): return server.create_temporary_credential_response(request)底层流程对应 rfc5849/authorization_server.py校验请求方法必须是 POST否则抛MethodNotAllowedError、校验必需的oauth_consumer_key与oauth_callback回调必须是合法 URL 或oob值、通过client_id查找客户端、再校验时间戳/nonce 与签名。全部通过后生成临时凭证并返回oauth_token、oauth_token_secret、oauth_callback_confirmedtrue。2. 资源所有者授权端点Authorization EndpointOAuth 1.0 客户端会把用户重定向到该授权页面由资源所有者批准或拒绝请求from django.shortcuts import render def authorize(request): # 此处需自行确保用户已登录 if request.method GET: try: req server.check_authorization_request(request) context {req: req} return render(request, authorize.html, context) except OAuth1Error as error: context {error: error} return render(request, error.html, context) granted request.POST.get(granted) if granted: grant_user request.user else: grant_user None try: return server.create_authorization_response(request, grant_user) except OAuth1Error as error: context {error: error} return render(request, error.html, context)其中OAuth1Error等错误类型从authlib.oauth1.rfc5849.errors或authlib.oauth1.errors导入完整错误清单见 errors.py包括invalid_client、invalid_token、invalid_signature、invalid_nonce、access_denied等。check_authorization_request()调用validate_authorization_request()authorization_server.py要求请求携带oauth_token并据此从缓存取出临时凭证。create_authorization_response()的语义是若grant_user为None用户拒绝则 302 重定向到回调地址并附access_denied错误参数若用户批准则生成 verifier 并以 302 重定向到回调地址附带oauth_token与oauth_verifier参数authorization_server.py。回调地址优先使用临时凭证中的oauth_callback若为oob则回退到客户端的default_redirect_uri。3. 令牌端点Token Endpoint客户端使用临时凭证与oauth_verifier换取令牌凭证from django.views.decorators.http import require_http_methods require_http_methods([POST]) def issue_token(request): return server.create_token_response(request)create_token_response()的校验流程见 authorization_server.py依次校验oauth_consumer_key、客户端存在性、oauth_token、缓存中的临时凭证、oauth_verifier是否与临时凭证匹配、时间戳/nonce 与签名。全部通过后调用create_token_credential()落库生成令牌凭证并在响应后删除缓存中的临时凭证返回oauth_token与oauth_token_secret。4. 注册 URL 路由最后把上述视图注册到 Django 的 url patterns 中例如from django.urls import path urlpatterns [ path(oauth/initiate, initiate_temporary_credential, nameinitiate), path(oauth/authorize, authorize, nameauthorize), path(oauth/token, issue_token, nametoken), ]仓库测试中对应的路由语义为/oauth/initiate、/oauth/authorize、/oauth/token可参考 tests/django/test_oauth1/test_authorize.py 与 tests/django/test_oauth1/test_token_credentials.py。服务端配置项详解BaseServer与ResourceProtector都从 Django 设置中的AUTHLIB_OAUTH1_PROVIDER字典读取配置见 authorization_server.py 与 resource_protector.py配置键作用默认值signature_methods允许的签名方法列表如[HMAC-SHA1]、[PLAINTEXT]、[RSA-SHA1][HMAC-SHA1]来自 base_server.py 的SUPPORTED_SIGNATURE_METHODSnonce_expires_innonce 在缓存中的保留时长秒用于防重放86400temporary_credential_expires_in临时凭证在缓存中的过期时间秒仅CacheAuthorizationServer使用86400temporary_credential_key_prefix临时凭证缓存键前缀仅CacheAuthorizationServer使用temporary_credential:配置示例放在 Django settings 中AUTHLIB_OAUTH1_PROVIDER { signature_methods: [HMAC-SHA1, PLAINTEXT, RSA-SHA1], nonce_expires_in: 86400, temporary_credential_expires_in: 3600, }仓库测试 tests/django/test_oauth1/conftest.py 演示了通过settings.AUTHLIB_OAUTH1_PROVIDER {signature_methods: [PLAINTEXT]}切换签名方法的用法。签名方法与时间戳校验Authlib 依据 RFC 5849 实现了三种签名方法见 signature.pyHMAC-SHA1默认支持、RSA-SHA1、PLAINTEXT。校验逻辑在 base_server.py时间戳必须是正整数且与当前时间之差不能超过EXPIRY_TIME默认 300 秒见 base_server.pynonce 必须唯一重复使用同一 nonce 会触发InvalidNonceErrorPLAINTEXT方法下时间戳与 nonce 可省略规范允许如需扩展自定义签名方法可通过Server.register_signature_method(name, verify)注册。nonce 在 Django 中的去重基于缓存实现键格式为nonce:{nonce}-{timestamp}-{client_id}若请求携带令牌还会追加-{token}见 nonce.py第一次出现时写入缓存并返回False已存在则返回True触发重放拒绝。保护资源ResourceProtector资源服务器可以与授权服务器分离部署。用ResourceProtector包装视图即可保护用户资源from django.http import JsonResponse from authlib.integrations.django_oauth1 import ResourceProtector require_oauth ResourceProtector(Client, TokenCredential) require_oauth def user_api(request): user request.oauth1_credential.user return JsonResponse(dict(usernameuser.username))require_oauth装饰器会向request注入oauth1_credential属性它正是Token 模型的实例因此可以直接通过request.oauth1_credential.user拿到资源所有者。从源码 resource_protector.py 可以看到其完整机制get_token_credential()按client_id与oauth_token两个条件从数据库查询令牌acquire_credential()将 Django 请求封装为OAuth1Request并调用validate_request()位于 rfc5849/resource_protector.py依次校验oauth_consumer_key、客户端、oauth_token、令牌凭证、时间戳/nonce 与签名装饰器同时支持require_oauth与require_oauth(realm...)两种写法见 resource_protector.py校验失败时返回包含错误信息的 JSON 响应并设置Cache-Control: no-store与Pragma: no-cache头。仓库测试 tests/django/test_oauth1/test_resource_protector.py 覆盖了三种签名方法下的成功与失败场景例如缺失oauth_consumer_key返回missing_required_parameter、未知客户端返回invalid_client、重复 nonce 返回invalid_nonce、错误签名返回invalid_signature。端到端测试验证完整的 Django OAuth 1.0 测试位于 tests/django/test_oauth1/conftest.py构造CacheAuthorizationServer(Client, TokenCredential)并分别提供 HMAC-SHA1、PLAINTEXT、RSA-SHA1 三种签名方法的服务器夹具models.py测试用的 Client 与 TokenCredential 模型RSA 场景下get_rsa_public_key()返回 tests/files/rsa_public.pemtest_authorize.py验证授权批准302 重定向携带oauth_verifier与授权拒绝302 重定向携带access_deniedtest_token_credentials.py验证令牌端点对参数缺失、重复 OAuth 参数、错误签名、重复 nonce 的响应以及三种签名方法下的成功换发test_resource_protector.py验证资源保护装饰器的完整鉴权链路。总结在 Django 中搭建 OAuth 1.0 Provider 只需三步定义继承ClientMixin的 Client 模型与继承TokenCredentialMixin的 Token 模型、用CacheAuthorizationServer(Client, Token)实例化授权服务器并实现三个端点视图、用ResourceProtector(Client, Token)守护受保护资源。临时凭证、时间戳与 nonce 全部由 Django 缓存内置处理令牌凭证持久化入库且永不过期——这就是 Authlib 为 Django 提供的 OAuth 1.0 服务端完整方案。更深入的 API 说明可继续阅读 Django OAuth 1.0 Server API 参考客户端接入可参考 Django OAuth 1.0 客户端集成。赞分享【免费下载链接】authlibThe ultimate Python library in building OAuth, OpenID Connect clients and servers. JWS, JWE, JWK, JWA, JWT included.项目地址https://gitcode.com/gh_mirrors/au/authlib点击查看免费下载相关推荐大麦抢票自动化怎么装、怎么配、怎么跑通大麦抢票自动化怎么装、怎么配、怎么跑通 开票前 30 秒刷新键按到发烫屏幕上还是灰掉的暂未开售时间一到你的手永远比网络请求慢半拍——这是所有抢过票使用 Authlib 在 Flask 中构建 OAuth 1.0 Provider授权服务器与资源服务器完整实战指南使用 Authlib 在 Flask 中构建 OAuth 1.0 Provider授权服务器与资源服务器完整实战指南 Authlib 提供了开箱即用的 FlaAuthlib 实战在 Django 中构建 OAuth 2.0 授权服务器与 OpenID Connect ProviderAuthlib 实战在 Django 中构建 OAuth 2.0 授权服务器与 OpenID Connect Provider 本指南以 Authlib 官方上一篇九大网盘直链解析神器免费解锁全平台高速下载终极指南下一篇5个高效技巧全面掌握绝区零自动化工具OneDragon创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站