diff --git a/archery/settings.py b/archery/settings.py index 2f1698423e..0a01726696 100644 --- a/archery/settings.py +++ b/archery/settings.py @@ -7,6 +7,12 @@ from datetime import timedelta import environ import requests +import logging + +logging.basicConfig( + level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" +) +logger = logging.getLogger(__name__) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -17,8 +23,13 @@ SECRET_KEY=(str, "hfusaf2m4ot#7)fkw#di2bu6(cv0@opwmafx5n#6=3d%x^hpl6"), DATABASE_URL=(str, "mysql://root:@127.0.0.1:3306/archery"), CACHE_URL=(str, "redis://127.0.0.1:6379/0"), + # 系统外部认证目前支持LDAP、OIDC、DINGDING三种,认证方式只能启用其中一种,如果启用多个,实际生效的只有一个,优先级LDAP > DINGDING > OIDC ENABLE_LDAP=(bool, False), ENABLE_OIDC=(bool, False), + ENABLE_DINGDING=( + bool, + False, + ), # 钉钉认证方式参考文档:https://open.dingtalk.com/document/orgapp/tutorial-obtaining-user-personal-information AUTH_LDAP_ALWAYS_UPDATE_USER=(bool, True), AUTH_LDAP_USER_ATTR_MAP=( dict, @@ -236,7 +247,7 @@ INSTALLED_APPS += ("mozilla_django_oidc",) MIDDLEWARE += ("mozilla_django_oidc.middleware.SessionRefresh",) AUTHENTICATION_BACKENDS = ( - "oidc.auth.OIDCAuthenticationBackend", + "common.authenticate.oidc_auth.OIDCAuthenticationBackend", "django.contrib.auth.backends.ModelBackend", ) @@ -260,6 +271,20 @@ LOGIN_REDIRECT_URL = "/" +# Dingding +ENABLE_DINGDING = env("ENABLE_DINGDING", False) +if ENABLE_DINGDING: + INSTALLED_APPS += ("django_auth_dingding",) + AUTHENTICATION_BACKENDS = ( + "common.authenticate.dingding_auth.DingdingAuthenticationBackend", + "django.contrib.auth.backends.ModelBackend", + ) + AUTH_DINGDING_AUTHENTICATION_CALLBACK_URL = env( + "AUTH_DINGDING_AUTHENTICATION_CALLBACK_URL" + ) + AUTH_DINGDING_APP_KEY = env("AUTH_DINGDING_APP_KEY") + AUTH_DINGDING_APP_SECRET = env("AUTH_DINGDING_APP_SECRET") + # LDAP ENABLE_LDAP = env("ENABLE_LDAP", False) if ENABLE_LDAP: @@ -293,6 +318,28 @@ ) # 每次登录从ldap同步用户信息 AUTH_LDAP_USER_ATTR_MAP = env("AUTH_LDAP_USER_ATTR_MAP") +SUPPORTED_AUTHENTICATION = [ + ("LDAP", ENABLE_LDAP), + ("DINGDING", ENABLE_DINGDING), + ("OIDC", ENABLE_OIDC), +] +# 计算当前启用的外部认证方式数量 +ENABLE_AUTHENTICATION_COUNT = len( + [enabled for (name, enabled) in SUPPORTED_AUTHENTICATION if enabled] +) +if ENABLE_AUTHENTICATION_COUNT > 0: + if ENABLE_AUTHENTICATION_COUNT > 1: + logger.warning( + "系统外部认证目前支持LDAP、DINGDING、OIDC三种,认证方式只能启用其中一种,如果启用多个,实际生效的只有一个,优先级LDAP > DINGDING > OIDC" + ) + authentication = "" # 默认为空 + for name, enabled in SUPPORTED_AUTHENTICATION: + if enabled: + authentication = name + break + logger.info("当前生效的外部认证方式:" + authentication) + logger.info("认证后端:" + AUTHENTICATION_BACKENDS.__str__()) + # LOG配置 LOGGING = { "version": 1, diff --git a/archery/urls.py b/archery/urls.py index cb455ab98a..e24e00eb52 100644 --- a/archery/urls.py +++ b/archery/urls.py @@ -6,6 +6,7 @@ path("admin/", admin.site.urls), path("api/", include(("sql_api.urls", "sql_api"), namespace="sql_api")), path("oidc/", include("mozilla_django_oidc.urls")), + path("dingding/", include("django_auth_dingding.urls")), path("", include(("sql.urls", "sql"), namespace="sql")), ] diff --git a/common/authenticate/__init__.py b/common/authenticate/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/common/authenticate/dingding_auth.py b/common/authenticate/dingding_auth.py new file mode 100644 index 0000000000..091ba80b90 --- /dev/null +++ b/common/authenticate/dingding_auth.py @@ -0,0 +1,10 @@ +from django_auth_dingding import auth +from common.auth import init_user + + +class DingdingAuthenticationBackend(auth.DingdingAuthenticationBackend): + def create_user(self, claims): + """Return object for a newly created user account.""" + user = super().create_user(claims) + init_user(user) + return user diff --git a/oidc/auth.py b/common/authenticate/oidc_auth.py similarity index 100% rename from oidc/auth.py rename to common/authenticate/oidc_auth.py diff --git a/common/middleware/check_login_middleware.py b/common/middleware/check_login_middleware.py index ec78d697d9..9d906f9929 100644 --- a/common/middleware/check_login_middleware.py +++ b/common/middleware/check_login_middleware.py @@ -12,6 +12,8 @@ "/oidc/callback/", "/oidc/authenticate/", "/oidc/logout/", + "/dingding/callback/", + "/dingding/authenticate/", ] IGNORE_URL_RE = r"/api/(v1|auth)/\w+" diff --git a/common/templates/login.html b/common/templates/login.html index 5ef904e1bc..a015074b2f 100644 --- a/common/templates/login.html +++ b/common/templates/login.html @@ -43,6 +43,11 @@ 以OIDC登录 {% endif %} + {% if dingding_enabled %} +
+ 以钉钉登录 +
+ {% endif %} diff --git a/requirements.txt b/requirements.txt index 9c30bdfda9..dea978ef6c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -38,3 +38,4 @@ django-environ==0.8.1 alibabacloud_dysmsapi20170525==2.0.9 tencentcloud-sdk-python==3.0.656 mozilla-django-oidc==3.0.0 +django-auth-dingding==0.0.2 \ No newline at end of file diff --git a/sql/views.py b/sql/views.py index a002b5ad66..4c494e69f3 100644 --- a/sql/views.py +++ b/sql/views.py @@ -1,8 +1,6 @@ # -*- coding: UTF-8 -*- import os import traceback - -import simplejson as json from django.conf import settings from django.contrib.auth.decorators import permission_required @@ -65,7 +63,8 @@ def login(request): "login.html", context={ "sign_up_enabled": SysConfig().get("sign_up_enabled"), - "oidc_enabled": os.getenv("ENABLE_OIDC"), + "oidc_enabled": settings.ENABLE_OIDC, + "dingding_enabled": settings.ENABLE_DINGDING, }, )