快速简单地在您的Django项目中实现SAML单点登录。
项目描述
Django SAML工具包
快速简单地将SAML单点登录添加到您的Django项目中。此包设计得非常简单,易于初始设置,同时也很容易自定义以满足所有需求。
安装
依赖项(Linux)
此功能需要xmlsec1包。
Debian / Ubuntu
sudo apt-get install libxml2-dev libxmlsec1-dev libxmlsec1-openssl
Red Hat / CentOs
sudo yum install libxml2-devel xmlsec1-devel xmlsec1-openssl-devel libtool-ltdl-devel
依赖项(Windows)
Windows上的python-xmlsec包存在一些托管问题,因此您可以在此处手动安装它
pip install https://github.com/mehcode/python-xmlsec/releases/download/1.3.5/xmlsec-1.3.52.dev0-cp36-cp36m-win_amd64.whl
更多信息请参见此处的相关问题。
Pip
pip install python3-saml-django
Django
注意:在1.2.0版本中删除了对Django 1.11的支持。如果您需要Django 1.11支持,请使用版本1.1.4。在1.3.0版本中删除了对Django 2.x的支持。如果您需要Django 2.x支持,请使用版本1.2.2。
settings.py
INSTALLED_APPS = [
...,
'django_saml'
]
AUTHENTICATION_BACKENDS = [
'django_saml.backends.SamlUserBackend',
...
]
urls.py
urlpatterns = [
path('saml/', include('django_saml.urls')),
...
]
配置
必需设置
SP信息
您必须提供有关您站点的信息以发布为元数据。
SAML_SP = {
"entityId": "https://<your_site>/saml/metadata/",
"assertionConsumerService": {
"url": "https://<your_site>/saml/acs/",
# DO NOT CHANGE THIS
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
},
"singleLogoutService": {
"url": "https://<your_site>/saml/sls/",
# DO NOT CHANGE THIS
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
},
"NameIDFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified",
"x509cert": "<can also be loaded by file, see SAML_BASE_DIRECTORY>",
"privateKey": "<can also be loaded by file, see SAML_BASE_DIRECTORY>"
}
IdP信息
您必须通过以下方式之一提供您将要使用的IdP的信息
SAML_IDP = {
"entityId": "https://example.com/saml/metadata/",
"singleSignOnService": {
"url": "https://example.com/trust/saml2/http-post/sso/",
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
},
"singleLogoutService": {
"url": "https://example.com/trust/saml2/http-redirect/slo/",
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
},
"x509cert": "<cert here>"
}
SAML_IDP_FILE = os.path.join(BASE_DIR, 'idp_meta.xml')
SAML_IDP_URL = 'https://example.com/saml/metadata/'
可选设置
设置 | 描述 | 默认 | 示例 |
---|---|---|---|
SAML_STRICT | 应拒绝错误的SAML响应。在生产环境中应设置为True。 | True | |
SAML_DEBUG | 显示SAML警告 | False | |
SAML_CREATE_USER | 如果用户不存在,则在登录时创建新用户 | True | |
SAML_UPDATE_USER | 登录时使用SAML信息更新现有用户 | False | |
SAML_IDP_METADATA_TIMEOUT | 如果使用SAML_IDP_URL,则在再次检查之前将结果缓存这么长时间。 | 3600 | |
SAML_SECURITY | 高级安全设置 | 见下文 | 见下文 |
SAML_CONTACT | 网站维护者的联系信息 | 无 | 见下文 |
SAML_ORGANIZATION | 组织信息 | 无 | 见下文 |
SAML_LOGIN_REDIRECT | 登录成功后重定向用户的路径 | '/' | |
SAML_LOGOUT_REDIRECT | 登录成功后重定向用户的路径 | '/logged-out' | |
SAML_NO_USER_REDIRECT | 如果SAML_CREATE_USER = False且用户不存在,则重定向用户的路径 | 无(引发PermissionDenied) | '/permission-error' |
SAML_USERNAME_ATTR | 用于查找用户的SAML属性(名称,而不是友好名称) | 'uid' | 'email' |
SAML_ATTR_MAP | 将SAML属性映射到Django用户属性的2-元组列表(按名称索引,而不是友好名称) | [] | [('givenName', 'first_name')] |
SAML_ATTR_DEFAULTS | 如果SAML响应中不存在属性,则使用默认值。如果不存在默认值,则抛出MissingAttributeException 。 |
{} | {'first_name': ''} |
SAML_ATTR_UPDATE_IGNORE | 仅在首次登录时设置,并在后续登录中忽略的Django用户属性列表(仅当SAML_UPDATE_USER为True 时使用) |
[] | [('email', 'first_name')] |
SAML_BASE_DIRECTORY | 加载SP证书的文件路径。必须包含一个包含'sp.key'和'sp.crt'的'certs'文件夹。 | 无 | os.path.join(BASE_DIR, 'saml') |
SAML_DESTINATION_HOST | 与SAML Destination属性进行比较的静态值,而不是从请求中读取。对于负载均衡器很有用。 | 无 | 'example.com' |
SAML_DESTINATION_HTTPS | SAML_DESTINATION_HOST的配套设置。如果目标将通过HTTPS但最终请求不会,则设置为True。 | 无 | True |
SAML_DESTINATION_PORT | SAML_DESTINATION_HOST的配套设置。如果您使用一个非标准端口且不匹配SAML_DESTINATION_HTTPS,则设置为数字的字符串。 | 无 | '8080' |
SAML_SECURITY 默认和示例
SAML_SECURITY = {
"nameIdEncrypted": False,
"authnRequestsSigned": False,
"logoutRequestSigned": False,
"logoutResponseSigned": False,
"signMetadata": False,
"wantMessagesSigned": False,
"wantAssertionsSigned": False,
"wantNameId": True,
"wantNameIdEncrypted": False,
"wantAssertionsEncrypted": False,
"signatureAlgorithm": "http://www.w3.org/2000/09/xmldsig#rsa-sha1",
"digestAlgorithm": "http://www.w3.org/2000/09/xmldsig#sha1"
}
SAML_CONTACT 示例
SAML_CONTACT = {
"technical": {
"givenName": "Technology Director",
"emailAddress": "technology@thon.org"
},
"support": {
"givenName": "Lead Systems Admin",
"emailAddress": "systems@thon.org"
}
}
SAML_ORGANIZATION 示例
SAML_ORGANIZATION = {
'en-US': {
'name': 'thon',
'displayname': 'THON',
'url': 'thon.org'
}
}
关于属性的一些说明
所有SAML属性都必须有一个名称,但有时它们可能有FriendlyName
。本库中的所有配置设置都依赖于正常名称,而不是友好名称。请参考您的IdP的属性设置或分析一个SAML响应以查看可用的属性。
一些IdP使用像urn:oid:2.5.4.42
这样的晦涩名称,而其他IdP使用firstName
;文档中使用看起来友好的名称并不意味着它是FriendlyName
。
高级配置(自定义后端)
对于如高级属性映射与组、转换SAML属性等场景,您可以创建自定义后端以替代默认后端。
示例
from django.contrib.auth.models import Group
from django_saml.backends import SamlUserBackend
class CustomSamlBackend(SamlUserBackend):
def clean_username(self, username):
"""Return the first part of the email address.
Example: test@example.com -> test.
"""
return username.split('@')[0]
def configure_user(self, session_data, user, ignore_fields=None):
"""Custom attribute mapping with groups.
NOTE: ALL SAML attributes in session_data are arrays, even if there is only one element.
"""
# Call super() to take care of the simple attribute mapping in SAML_ATTR_MAP
user = super(CustomSamlBackend, self).configure_user(session_data, user, ignore_fields=ignore_fields)
for group_name in session_data['psMemberOf']:
group_name = group_name[5:]
g = Group.objects.get(name=group_name)
g.user_set.add(user)
return user
致谢
此项目是围绕OneLogin的python3-saml库的一个包装器。
支持
如果您想支持此包的开发,请考虑向THON捐赠并支持我们的使命。
项目详情
下载文件
下载适用于您平台的文件。如果您不确定选择哪一个,请了解有关安装包的更多信息。