使用对称密钥算法对数据进行签名和验证(字典、字符串)。
项目描述
允许您使用对称密钥算法加密轻松地对数据进行签名。允许您验证已签名的数据并识别可能的验证错误。使用sha-(1, 224, 256, 385和512)/hmac进行签名加密。允许使用自定义哈希算法。提供用于签名(和验证)字典和URL的快捷函数。
关键概念
相互通信的主机共享密钥,该密钥用于签名数据(请求)。密钥永远不会被发送。
以下是一个案例:HTTP请求的签名。每个(HTTP)请求在发送端使用共享密钥签名,并产生三元组(签名,认证用户,有效期至),用于签名请求。
签名 (str):生成的签名。
认证用户 (str):发起请求的用户。可以是任何内容。
有效期至 (float 或 str):签名的过期时间(Unix时间戳)。
在接收端,使用共享密钥验证(HTTP请求)数据。检查签名是否有效且未过期。
┌─────────────┐ Data ┌─────────────┐
│ Host 1 ├────────────────────────────>│ Host 2 │
│ ─────────── │ │ ─────────── │
│ secret key │ │ secret key │
│ 'my-secret' │<────────────────────────────┤ 'my-secret' │
└─────────────┘ Data └─────────────┘
功能
核心 ska 模块
签名字典。
验证签名字典。
签名URL。添加并签名额外的URL数据。
验证URL。
使用内置算法之一(HMAC SHA-1、HMAC SHA-224、HMAC SHA-256、HMAC SHA-384或HMAC SHA-512)或定义一个自定义算法。
Django ska 模块 (ska.contrib.django.ska)
用于签名绝对URL的模型装饰器。仅对授权方保护视图(不需要认证)的视图(包括基于类的视图)装饰器。
基于使用 ska 生成的签名(令牌)的 Django 认证后端,允许您实现无密码登录 Django 网站。支持多个密钥(每个提供者)。包含方便的回调(可以按提供者进行自定义),用于各种认证状态。
模板标签,用于在模板中签名URL。
django-constance 集成(用于无密码认证)。
Django REST Framework 集成(用于保护 ViewSets,获取 JWT 令牌进行认证)。
先决条件
当前
核心 ska 模块需要 Python 3.8、3.9、3.10 和 3.11。
Django ska 模块 (ska.contrib.django.ska) 需要上述内容加上 Django 3.2、4.1 或 4.2。此外,还需要某些版本的 django-constance 和 djangorestframework。具体的版本要求主要取决于使用的 Django 版本。查看 示例要求,以了解与特定 Django 版本一起测试过的 django-constance 和 djangorestframework 的版本。
过去
在版本 1.10 中宣布将停止支持 Python 3.6 和 3.7。截至 1.9.1,一切仍然正常工作。
在版本 1.8 中宣布将停止支持 Python 2.7 和 3.5。截至 1.7.5,一切仍然正常工作。
在版本 1.6.8 中宣布将停止支持 Python 3.4。截至 1.6.8,一切仍然正常工作。
在版本 1.10 中宣布将停止支持 Django 2.2、3.0、3.1 和 4.0。截至 1.9.1,一切仍然是向后兼容的。
在版本 1.6 中宣布将停止支持 Django 1.5、1.6 和 1.7。截至 1.6,一切仍然是向后兼容的。
在版本 1.6 中宣布将停止支持 Python 2.6 和 3.3。截至 1.6,一切仍然是向后兼容的(在可能的范围内)。
生态系统
需要用于其他语言的 ska 吗?请查看以下关联项目
在 Python、NodeJS 和 PHP 实现之间生成的签名是互兼容的。
安装
来自 PyPI 的最新稳定版本
pip install ska
或来自 GitHub 的最新开发版本。
pip install https://github.com/barseghyanartur/ska/archive/main.tar.gz
使用示例
有关与Django的集成,请参阅Django集成部分。
基本用法
纯Python使用。
发送方
签名URL非常简单,如下所示。
所需的导入。
from ska import sign_url
生成签名URL。
signed_url = sign_url(
auth_user='user',
secret_key='your-secret_key',
url='http://e.com/api/'
)
GET http://e.com/api/?valid_until=1378045287.0&auth_user=user&signature=YlZpLFsjUKBalL4x5trhkeEgqE8%3D
签名默认有效期是10分钟(600秒)。如果您想使用不同的有效期,请向sign_url
函数提供lifetime
参数。
默认情况下,包含生成的签名值的(GET)参数名称是signature
。如果您想使用不同的名称,请向sign_url
函数提供signature_param
参数。
默认情况下,包含auth_user
值的(GET)参数名称是auth_user
。如果您想使用不同的名称,请向sign_url
函数提供auth_user_param
参数。
默认情况下,包含valid_until
值的(GET)参数名称是valid_until
。如果您想使用不同的名称,请向sign_url
函数提供valid_until_param
参数。
注意,默认情况下,在给定的url
和生成的签名参数之后会添加一个后缀‘?’。如果您想使用自定义后缀,请向sign_url
函数提供suffix
参数。如果您想去掉后缀,将其值设置为空字符串。
经过所有自定义后,它看起来如下所示
from ska import HMACSHA512Signature # Use HMAC SHA-512 algorithm
signed_url = sign_url(
auth_user='user',
secret_key='your-secret_key',
lifetime=120,
url='http://e.com/api/',
signature_param='signature',
auth_user_param='auth_user',
valid_until_param='valid_until',
signature_cls=HMACSHA512Signature
)
您还可以通过提供extra
参数(字典)来向签名中添加额外的数据。注意,附加数据也会被签名。如果请求被篡改(值与最初提供的值不同),签名将变得无效。
sign_url(
auth_user='user',
secret_key='your-secret_key',
url='http://e.com/api/',
extra={
'email': 'doe@example.com',
'last_name': 'Doe',
'first_name': 'Joe'
}
)
现在您可以继续使用签名URL进行请求。如果您使用著名的requests
库,它将是如下所示。
import requests
requests.get(signed_url)
如果您想使用POST方法,您可能需要获取一个字典,以便稍后将其附加到POST数据中。
所需的导入。
from ska import signature_to_dict
生成包含签名数据的字典,准备将其放入请求(例如POST)数据中。上述所有针对sign_url
函数的自定义设置也适用于signature_to_dict
signature_dict = signature_to_dict(
auth_user='user',
secret_key='your-secret_key'
)
{
'signature': 'YlZpLFsjUKBalL4x5trhkeEgqE8=',
'auth_user': 'user',
'valid_until': '1378045287.0'
}
向签名添加附加数据的方式相同
signature_dict = signature_to_dict(
auth_user='user',
secret_key='your-secret_key',
extra={
'email': 'john.doe@mail.example.com',
'first_name': 'John',
'last_name': 'Doe'
}
)
{
'auth_user': 'user',
'email': 'john.doe@mail.example.com',
'extra': 'email,first_name,last_name',
'first_name': 'John',
'last_name': 'Doe',
'signature': 'cnSoU/LnJ/ZhfLtDLzab3a3gkug=',
'valid_until': 1387616469.0
}
如果您出于某种原因更喜欢更低级别的实现,请阅读高级用法(低级别)章节中的相同部分。
接收方
验证签名请求数据非常简单,如下所示。
所需的导入。
from ska import validate_signed_request_data
验证签名请求数据。注意,data
值预期为字典;这里以request.GET
为例。它可能会因您的框架而异(除非您使用Django)。
validation_result = validate_signed_request_data(
data=request.GET, # Note, that ``request.GET`` is given as example.
secret_key='your-secret_key'
)
validate_signed_request_data
生成一个ska.SignatureValidationResult
对象,该对象包含以下数据。
result
(bool
):如果数据有效,则为True。否则为False。reason
(list
):字符串列表,指示验证错误。如果result
为True,则为空列表。
默认情况下,包含签名值的(GET)参数名称是signature
。如果您想使用不同的名称,请向validate_signed_request_data
函数提供signature_param
参数。
默认情况下,包含auth_user
值的(GET)参数名称是auth_user
。如果您想使用不同的名称,请向validate_signed_request_data
函数提供auth_user_param
参数。
默认的(GET)参数名称为valid_until
,表示有效期限。如果您想使用不同的名称,请向validate_signed_request_data
函数提供valid_until_param
参数。
在所有自定义设置下,它将如下所示。注意,这里以request.GET
为例。
from ska import HMACSHA256Signature # Use HMAC SHA-256 algorithm
validation_result = validate_signed_request_data(
data=request.GET,
secret_key='your-secret_key',
signature_param='signature',
auth_user_param='auth_user',
valid_until_param='valid_until',
signature_cls=HMACSHA256Signature
)
如果您出于某种原因更喜欢更低级别的实现,请阅读高级用法(低级别)章节中的相同部分。
命令行使用
可以使用ska.generate_signed_url
模块从命令行生成签名URL。
- 参数:
-h, --help show this help message and exit
-au AUTH_USER, --auth-user AUTH_USER
`auth_user` value
-sk SECRET_KEY, --secret-key SECRET_KEY
`secret_key` value
-vu VALID_UNTIL, --valid-until VALID_UNTIL
`valid_until` value
-l LIFETIME, --lifetime LIFETIME
`lifetime` value
-u URL, --url URL URL to sign
-sp SIGNATURE_PARAM, --signature-param SIGNATURE_PARAM
(GET) param holding the `signature` value
-aup AUTH_USER_PARAM, --auth-user-param AUTH_USER_PARAM
(GET) param holding the `auth_user` value
-vup VALID_UNTIL_PARAM, --valid-until-param VALID_UNTIL_PARAM
(GET) param holding the `auth_user` value
- 示例:
ska-sign-url -au user -sk your-secret-key --url http://example.com
高级使用(低级)
发送方
所需的导入。
from ska import Signature, RequestHelper
生成签名。
signature = Signature.generate_signature(
auth_user='user',
secret_key='your-secret-key'
)
签名的默认有效期为10分钟(600秒)。如果您想设置不同的有效期,请向generate_signature
方法提供lifetime
参数。
signature = Signature.generate_signature(
auth_user='user',
secret_key='your-secret-key',
lifetime=120 # Signature lifetime set to 120 seconds.
)
向签名中添加额外的数据与sign_url
的方式相同。
signature = Signature.generate_signature(
auth_user='user',
secret_key='your-secret-key',
extra={
'email': 'doe@example.com',
'last_name': 'Doe',
'first_name': 'Joe'
}
)
对于HMAC SHA-384算法,它将如下所示。
from ska import HMACSHA384Signature
signature = HMACSHA384Signature.generate_signature(
auth_user='user',
secret_key='your-secret-key'
)
您的端点使用特定的参数名称,并且您需要将生成的签名参数封装到URL中。为了轻松完成任务,请创建一个请求助手。将(GET)参数的名称输入到请求助手,并让它为您生成一个签名端点URL。
request_helper = RequestHelper(
signature_param='signature',
auth_user_param='auth_user',
valid_until_param='valid_until'
)
将签名参数附加到端点URL。
signed_url = request_helper.signature_to_url(
signature=signature,
endpoint_url='http://e.com/api/'
)
GET http://e.com/api/?valid_until=1378045287.0&auth_user=user&signature=YlZpLFsjUKBalL4x5trhkeEgqE8%3D
发送请求。
import requests
r = requests.get(signed_url)
对于HMAC SHA-384算法,它将如下所示。
from ska import HMACSHA384Signature
request_helper = RequestHelper(
signature_param='signature',
auth_user_param='auth_user',
valid_until_param='valid_until',
signature_cls=HMACSHA384Signature
)
signed_url = request_helper.signature_to_url(
signature=signature,
endpoint_url='http://e.com/api/'
)
接收方
所需的导入。
from ska import RequestHelper
创建请求助手。您的端点使用特定的参数名称。为了轻松完成任务,我们将这些参数输入到请求助手,并让它为我们提取签名请求中的数据。
request_helper = RequestHelper(
signature_param='signature',
auth_user_param='auth_user',
valid_until_param='valid_until'
)
验证请求数据。注意,这里以request.GET
为例。
validation_result = request_helper.validate_request_data(
data=request.GET,
secret_key='your-secret-key'
)
您的实现将取决于您自己,但可能如下所示。
if validation_result.result:
# Validated, proceed further
# ...
else:
# Validation not passed.
raise Http404(validation_result.reason)
您也可以通过调用ska.Signature
的validate_signature
方法来简单地验证签名。
Signature.validate_signature(
signature='EBS6ipiqRLa6TY5vxIvZU30FpnM=',
auth_user='user',
secret_key='your-secret-key',
valid_until='1377997396.0'
)
Django集成
ska
提供了Django模型-和视图装饰器来生成签名URL和验证端点,以及一个认证后端,允许使用ska
生成的签名令牌进行无密码登录到Django网站。还有一个用于签名URL的模板标签。
演示
为了能够快速评估ska
,已经创建了一个演示应用程序(带有快速安装程序)(在Ubuntu/Debian上运行,也可能在其他Linux系统上运行,但无法保证)。按照以下说明,在一分钟内运行演示。
获取最新的ska_example_app_installer.sh
并执行它
wget -O - https://raw.github.com/barseghyanartur/ska/stable/examples/ska_example_app_installer.sh | bash
打开您的浏览器并测试应用程序。
Foo列表(ska受保护的视图)
认证页面(ska认证后端)
Django管理界面
管理员用户名: test_admin
管理员密码: test
配置
密钥(str
)必须在您的项目中的settings
模块中定义。
SKA_SECRET_KEY = 'my-secret-key'
以下变量可以在您的项目中的settings
模块中重写。
SKA_UNAUTHORISED_REQUEST_ERROR_MESSAGE
(str
):纯文本错误消息。默认为“未经授权的请求。{0}”。SKA_UNAUTHORISED_REQUEST_ERROR_TEMPLATE
(str
):在发生401响应时应渲染的401模板的路径。默认为空字符串(未提供)。SKA_AUTH_USER
(str
):ska.sign_url
函数的auth_user
参数。默认为“ska-auth-user”。
请参阅工作的示例项目。
多个密钥
想象一下,你有一个网站,你想为各种客户/发件人提供无密码登录功能,并且你不想让他们共享一个密钥,而是拥有各自的密钥。此外,你还希望为每个单独的客户/发件人和不同类型的用户认证执行非常定制的回调。
┌────────────────┐
│ Site providing │
│ authentication │
│ ────────────── │
│ custom secret │
│ keys per │
│ client │
│ ────────────── │
│ Site 1: 'sk-1' │
┌───────────>│ Site 2: 'sk-2' │<───────────┐
│ │ Site 3: 'sk-3' │ │
│ ┌────>│ Site 4: 'sk-4' │<────┐ │
│ │ └────────────────┘ │ │
│ │ │ │
│ │ │ │
┌────────────┴─┐ ┌─┴────────────┐ ┌────────────┴─┐ ┌─┴────────────┐
│ Site 1 │ │ Site 2 │ │ Site 3 │ │ Site 4 │
│ ──────────── │ │ ──────────── │ │ ──────────── │ │ ──────────── │
│ secret key │ │ secret key │ │ secret key │ │ secret key │
│ 'sk-1' │ │ 'sk-2' │ │ 'sk-3' │ │ 'sk-4' │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
为了实现上述功能,引入了提供者概念。你可以定义一个密钥、回调或重定向URL。下面是一个示例。请注意,SKA_PROVIDERS(“client_1”,“client_2”等)的键是提供者密钥。
SKA_PROVIDERS = {
# ********************************************************
# ******************** Basic gradation *******************
# ********************************************************
# Site 1
'client_1': {
'SECRET_KEY': 'sk-1',
},
# Site 2
'client_2': {
'SECRET_KEY': 'sk-2',
},
# Site 3
'client_3': {
'SECRET_KEY': 'sk-3',
},
# Site 4
'client_4': {
'SECRET_KEY': 'sk-4',
},
# ********************************************************
# ******* You make gradation as complex as you wish ******
# ********************************************************
# Client 1, group users
'client_1.users': {
'SECRET_KEY': 'client-1-users-secret-key',
},
# Client 1, group power_users
'client_1.power_users': {
'SECRET_KEY': 'client-1-power-users-secret-key',
'USER_CREATE_CALLBACK': 'foo.ska_callbacks.client1_power_users_create',
},
# Client 1, group admins
'client_1.admins': {
'SECRET_KEY': 'client-1-admins-secret-key',
'USER_CREATE_CALLBACK': 'foo.ska_callbacks.client1_admins_create',
'REDIRECT_AFTER_LOGIN': '/admin/'
},
}
请参阅回调部分以获取回调列表。请注意,在SKA_PROVIDERS中定义的回调是覆盖。如果某个回调未在SKA_PROVIDERS中定义,则身份验证后端将回退到相应的默认回调函数。
显然,服务器必须定义完整的提供者列表。在客户端,你只需要存储通用密钥和当然提供者UID。
当在发送端创建签名URL时,你应该在extra参数中提供provider密钥。下面是一个如何为client_1.power_users执行的示例。
from ska import sign_url
from ska.defaults import DEFAULT_PROVIDER_PARAM
server_ska_login_url = 'https://server-url.com/ska/login/'
signed_remote_ska_login_url = sign_url(
auth_user='test_ska_user',
# Using provider-specific secret key. This value shall be equal to
# the value of SKA_PROVIDERS['client_1.power_users']['SECRET_KEY'],
# defined in your projects' Django settings module.
secret_key='client-1-power-users-secret-key',
url=server_ska_login_url,
extra={
'email': 'test_ska_user@mail.example.com',
'first_name': 'John',
'last_name': 'Doe',
# Using provider specific string. This value shall be equal to
# the key string "client_1.power_users" of SKA_PROVIDERS,
# defined in your projcts' Django settings module.
DEFAULT_PROVIDER_PARAM: 'client_1.power_users',
}
)
Django模型方法装饰器sign_url
这最有可能用于模块models(models.py)。
想象一下,你有一些对象列表,并且只想让授权方查看URL。你可以在渲染列表(HTML)时使用get_signed_absolute_url方法来保护这些URL。
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse
from ska.contrib.django.ska.decorators import sign_url
class FooItem(models.Model):
title = models.CharField(_("Title"), max_length=100)
slug = models.SlugField(unique=True, verbose_name=_("Slug"))
body = models.TextField(_("Body"))
# Unsigned absolute URL, which goes to the foo item detail page.
def get_absolute_url(self):
return reverse('foo.detail', kwargs={'slug': self.slug})
# Signed absolute URL, which goes to the foo item detail page.
@sign_url()
def get_signed_absolute_url(self):
return reverse('foo.detail', kwargs={'slug': self.slug})
请注意,sign_url装饰器接受以下可选参数。
auth_user(str):发起请求的用户的用户名。
secret_key:共享密钥。如果设置,则覆盖在项目中设置模块的SKA_SECRET_KEY变量。
valid_until(float或str):Unix时间戳。如果没有给出,则自动生成(现在 + 寿命)。
lifetime(int):签名寿命(秒)。
suffix(str):添加到endpoint_url之后并在附加签名参数之前的后缀。
signature_param(str):将包含生成的签名值的GET参数名称。
auth_user_param(str):将包含auth_user值的GET参数名称。
valid_until_param(str):将包含valid_until值的GET参数名称。
Django视图装饰器validate_signed_request
用于保护视图(file views.py)。应应用于需要签名请求的视图(端点)。如果不成功,将返回ska.contrib.django.ska.http.HttpResponseUnauthorized,它是Django的django.http.HttpResponse的子类。你可以提供自己的401错误模板。只需将设置模块中的SKA_UNAUTHORISED_REQUEST_ERROR_TEMPLATE指向正确的模板即可。请参阅ska/contrib/django/ska/templates/ska/401.html作为模板示例。
from ska.contrib.django.ska.decorators import validate_signed_request
# Your view that shall be protected
@validate_signed_request()
def detail(request, slug, template_name='foo/detail.html'):
# Your code
请注意,validate_signed_request装饰器接受以下可选参数。
secret_key (str) : 共享密钥。如果设置,将覆盖项目中设置模块中设置的 SKA_SECRET_KEY 变量。
signature_param (str): 存储签名字符串的(例如 GET 或 POST)参数名称。
auth_user_param (str): 存储认证用户字符串的(例如 GET 或 POST)参数名称。
valid_until_param (str): 存储有效直到日期字符串的(例如 GET 或 POST)参数名称。
如果你使用基于类的视图,请使用 m_validate_signed_request 装饰器代替 validate_signed_request。
身份验证后端
允许你获得 Django 网站的免密码登录。
目前有两个后端实现
SkaAuthenticationBackend: 使用标准 Django 设置。
SkaAuthenticationConstanceBackend: 依赖于 django-constance 提供的动态设置功能。
默认情况下,使用相同令牌的登录次数不受限制。如果你希望在第一次使用后令牌失效,请将以下变量设置为 True 在你的项目的 Django 设置模块中。
SKA_DB_STORE_SIGNATURES = True
SKA_DB_PERFORM_SIGNATURE_CHECK = True
SkaAuthenticationBackend
SkaAuthenticationBackend 使用标准 Django 设置。
接收方
收件人是尝试进行身份验证(登录)的主机(Django 网站)。在收件人端,以下内容应存在。
settings.py
AUTHENTICATION_BACKENDS = (
'ska.contrib.django.ska.backends.SkaAuthenticationBackend',
'django.contrib.auth.backends.ModelBackend',
)
INSTALLED_APPS = (
# ...
'ska.contrib.django.ska',
# ...
)
SKA_SECRET_KEY = 'secret-key'
SKA_UNAUTHORISED_REQUEST_ERROR_TEMPLATE = 'ska/401.html'
SKA_REDIRECT_AFTER_LOGIN = '/foo/logged-in/'
urls.py
urlpatterns = [
url(r'^ska/', include('ska.contrib.django.ska.urls')),
url(r'^admin/', include(admin.site.urls)),
]
回调函数
已经为身份验证后端实现了几个回调函数。
USER_VALIDATE_CALLBACK (str): 验证请求回调。创建用于允许添加自定义逻辑到传入的认证请求。主要目的是提供一个灵活的方式来抛出异常,如果传入的认证请求应该被阻止(例如,电子邮件或用户名在黑名单中,或者正好相反——不在白名单中)。USER_VALIDATE_CALLBACK的唯一目的是如果请求数据无效,则抛出django.core.PermissionDenied异常。在这种情况下,认证流程将中断。其他所有异常都将被简单地忽略(但记录),如果没有抛出异常,则继续正常流程。
USER_GET_CALLBACK (str): 如果成功从数据库中获取用户(现有用户),则触发。
USER_CREATE_CALLBACK (str): 用户创建后立即触发(用户不存在)。
USER_INFO_CALLBACK (str): 成功认证时触发。
回调函数的示例(假设它位于模块my_app.ska_callbacks中)
def my_callback(user, request, signed_request_data)
# Your code
…其中
user是django.contrib.auth.models.User实例。
request是django.http.HttpRequest实例。
signed_request_data是包含已签名请求数据的字典。
例如,如果您需要将用户分配到某些本地Django组,您可以在客户端指定组名(将其添加到extra字典中),然后在回调中根据该名称将用户添加到该组。
回调是回调函数的路径限定符。考虑到上面的例子,它将是my_app.ska_callbacks.my_callback。
在项目的设置模块中,为每个回调变量的名称前加上SKA_。
示例
SKA_USER_GET_CALLBACK = 'my_app.ska_callbacks.my_get_callback'
SKA_USER_CREATE_CALLBACK = 'my_app.ska_callbacks.my_create_callback'
发送方
发送者是用户通过使用已签名的URL认证到接收者的主机(另一个Django网站)。
在发送端,只需要存在Django的ska模块,以及当然是在服务器端相同的SECRET_KEY。进一步来说,服务器的ska登录URL(在我们的案例中是“/ska/login/”)应该使用ska进行签名(例如,使用sign_url函数)。auth_user参数将用作Django用户名。请参阅下面的示例。
from ska import sign_url
from ska.contrib.django.ska.settings import SECRET_KEY
server_ska_login_url = 'https://server-url.com/ska/login/'
signed_url = sign_url(
auth_user='test_ska_user_0',
secret_key=SECRET_KEY,
url=server_ska_login_url,
extra={
'email': 'john.doe@mail.example.com',
'first_name': 'John',
'last_name': 'Doe',
}
)
注意,extra字典是可选的!如果存在email、first_name和last_name键,在验证成功后,数据将被保存到用户的个人资料中。
将此代码放入视图,然后在模板上下文中提供生成的URL,并将其渲染为URL,以便用户可以点击它进行服务器认证。
def auth_to_server(request, template_name='auth_to_server.html'):
# Some code + obtaining the `signed_url` (code shown above)
context = {'signed_url': signed_url}
return render(request, template_name, context)
SkaAuthenticationConstanceBackend
依赖于由django-constance提供的动态设置功能。
仅提及与`SkaAuthenticationBackend`的差异。
settings.py
AUTHENTICATION_BACKENDS = (
'ska.contrib.django.ska.backends.constance_backend.SkaAuthenticationConstanceBackend',
'django.contrib.auth.backends.ModelBackend',
)
INSTALLED_APPS = (
# ...
'constance', # django-constance
'ska.contrib.django.ska',
'django_json_widget', # For nice admin JSON widget
# ...
)
CONSTANCE_CONFIG = {
'SKA_PROVIDERS': (
{}, # The default value
'JSON data', # Help text in admin
'JSONField_config', # Field config
)
}
CONSTANCE_ADDITIONAL_FIELDS = {
'JSONField_config': [
# `jsonfield2` package might be used for storing the JSON field,
# however, at the moment of writing it has a bug which makes
# the JSON invalid after the first save. To avoid that, it has
# been patched and resides in examples/simple/jsonfield2_addons/
# module.
'jsonfield2_addons.forms.JSONField',
{
'widget': 'django_json_widget.widgets.JSONEditorWidget',
}
],
}
CONSTANCE_BACKEND = 'constance.backends.redisd.RedisBackend'
CONSTANCE_REDIS_CONNECTION = {
'host': 'localhost',
'port': 6379,
'db': 0,
}
使用 DatabaseBackend 的样子如下
CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend'
INSTALLED_APPS = (
# ...
'constance.backends.database',
# ...
)
动态后端的快速演示
克隆此项目
git clone git@github.com:barseghyanartur/ska.git
安装/迁移
./scripts/install.sh
pip install -r examples/requirements/django_2_1.txt
./scripts/migrate.sh --settings=settings.constance_settings
运行
./scripts/runserver.sh --settings=settings.constance_settings
{
"client_1.users":{
"SECRET_KEY":"client-1-users-secret-key"
},
"client_1.power_users":{
"SECRET_KEY":"client-1-power-users-secret-key",
"USER_CREATE_CALLBACK":"foo.ska_callbacks.client1_power_users_create"
},
"client_1.admins":{
"SECRET_KEY":"client-1-admins-secret-key",
"USER_CREATE_CALLBACK":"foo.ska_callbacks.client1_admins_create",
"USER_GET_CALLBACK":"foo.ska_callbacks.client1_admins_get",
"USER_INFO_CALLBACK":"foo.ska_callbacks.client1_admins_info_constance",
"REDIRECT_AFTER_LOGIN":"/admin/auth/user/"
}
}
在另一个浏览器中打开 http://localhost:8000/foo/authenticate/ 并导航到 By provider 部分的 Success 表格列中的 Log in - client_1.admins 链接。点击后,您应该已登录。您已使用动态设置。
urls.py
django-constance 特定的视图和 URL 已使用。有关参考,请参阅 ska.contrib.django.ska.views.constance_views 和 ska.contrib.django.ska.urls.constance_urls。
urlpatterns = [
url(r'^ska/', include('ska.contrib.django.ska.urls.constance_urls')),
url(r'^admin/', include(admin.site.urls)),
]
自定义身份验证后端
要实现替代身份验证后端,请参阅以下示例
from constance import config
from ska.contrib.django.backends import BaseSkaAuthenticationBackend
class SkaAuthenticationConstanceBackend(BaseSkaAuthenticationBackend):
"""Authentication backend."""
def get_settings(self):
"""
:return:
"""
return config.SKA_PROVIDERS
就是这样。get_settings 方法应该返回的只是一个包含提供者数据的 dict(有关参考,请参阅多个密钥;`get_settings` 的返回值是 `SKA_PROVIDERS` 字典)。
清除旧签名数据
如果您有大量访客且将 SKA_DB_STORE_SIGNATURES 设置为 True,则您的数据库会增长。如果您想删除旧的签名令牌数据,您可能需要通过 cron job 执行以下命令。
./manage.py ska_purge_stored_signature_data
安全注意事项
从安全角度出发,您应该通过安全的 HTTP 连接提供服务以下页面
服务器登录页面 (/ska/login/).
包含身份验证链接的客户端页面。
Django REST 框架集成
权限类
为了保护未经系统实际认证的视图,已实现了特定的权限类(对于计划设置和提供者设置,以及平面和提供者设置与 django-constance 包结合使用)。
实现了以下权限类
SignedRequestRequired
ProviderSignedRequestRequired
ConstanceSignedRequestRequired
ConstanceProviderSignedRequestRequired
ProviderSignedRequestRequired 示例
from rest_framework.viewsets import ModelViewSet
from ska.contrib.django.ska.integration.drf.permissions import (
ProviderSignedRequestRequired
)
from .models import FooItem
from .serializers import FooItemSerializer
class FooItemViewSet(ModelViewSet):
"""FooItem model viewset."""
permission_classes = (ProviderSignedRequestRequired,)
queryset = FooItem.objects.all()
serializer_class = FooItemSerializer
签名请求
请求以相同的方式进行签名。示例代码
# Given that we have `auth_user`, `auth_user_email`, `provider_name`
# (and the rest), the code would look as follows:
from ska import sign_url
from ska.defaults import DEFAULT_PROVIDER_PARAM
extra = {
'email': auth_user_email,
'first_name': first_name,
'last_name': last_name,
}
if provider_name:
extra.update({DEFAULT_PROVIDER_PARAM: provider_name})
signed_url = sign_url(
auth_user=auth_user,
secret_key=secret_key,
url=url,
extra=extra
)
JWT 令牌用于身份验证
用于获取 JWT 令牌进行身份验证。这也与 django-constance 一起工作。
设置示例
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
URL 示例
urlpatterns = [
# ...
url(
r'^ska-rest/',
include('ska.contrib.django.ska.integration.drf.urls.jwt_token')
),
]
示例请求
http://localhost:8008/ska-rest/obtain-jwt-token/
?signature=P92KWDDe0U84Alvu0tvmYoi8e8s%3D
&auth_user=test_ska_user
&valid_until=1548195246.0
&extra=email%2Cfirst_name%2Clast_name
&email=test_ska_user%40mail.example.com
&first_name=John
&last_name=Doe
示例响应
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"token": "eyJ0eXAiO.eyJ1c2VyX2lkIjo.m_saOvyKBO3"
}
测试
只需键入
pytest
或使用 tox
tox
或使用 tox 检查特定环境
tox -e py39
或运行 Django 测试
python examples/simple/manage.py test ska --settings=settings.testing
编写文档
请保持以下层次结构。
=====
title
=====
header
======
sub-header
----------
sub-sub-header
~~~~~~~~~~~~~~
sub-sub-sub-header
++++++++++++++++++
sub-sub-sub-sub-header
^^^^^^^^^^^^^^^^^^^^^^
sub-sub-sub-sub-sub-header
**************************
许可协议
GPL-2.0-only OR LGPL-2.1-or-later
支持
有关任何问题,请联系作者部分提供的电子邮件。
项目详情
下载文件
下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。
源分发
构建分发
ska-1.10.tar.gz的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 7ac0be5d5dde47e60e01d6e375cd3b351280f97d2a49aeb8aac8320a94854e4e |
|
MD5 | f8242a9f407ecfc319cee045afcba2bb |
|
BLAKE2b-256 | 67229789fade2645882af81174ca1adafdac40a01cddc6492a4a772ae254db33 |
ska-1.10-py2.py3-none-any.whl的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | c92194ccaec0eb92b393a8d27a1efb7ab9dd62afadbb489f176a7eb64b351b1a |
|
MD5 | d8037baf37a5bf24d95eb18374effc9f |
|
BLAKE2b-256 | 29ce055b3f8f8cec7212fba54f0d7c694c7da5f64088a76be20c72cb3f008ede |