fix(auth): 第三方用户(saml2)登录规则设置无效 (#8648)

* fix: 修复 OpenID、CAS、SAML2登录规则设置无效

* refactor: auth_third_party_required写到一个地方和优化代码结构

* refactor: 优化代码结构

* refactor: 修改变量名称

Co-authored-by: huangzhiwen <zhiwen.huang@fit2cloud.com>
pull/8710/head
fit2bot 2022-08-09 11:24:28 +08:00 committed by GitHub
parent c295f1451a
commit 3951b8b080
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 118 additions and 2 deletions

View File

@ -1,11 +1,15 @@
import base64 import base64
from django.shortcuts import redirect, reverse from django.shortcuts import redirect, reverse, render
from django.utils.deprecation import MiddlewareMixin from django.utils.deprecation import MiddlewareMixin
from django.http import HttpResponse from django.http import HttpResponse
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext as _
from django.contrib.auth import logout as auth_logout
from apps.authentication import mixins
from common.utils import gen_key_pair from common.utils import gen_key_pair
from common.utils import get_request_ip
class MFAMiddleware: class MFAMiddleware:
@ -13,6 +17,7 @@ class MFAMiddleware:
这个 中间件 是用来全局拦截开启了 MFA 却没有认证的 OIDC, CAS使用第三方库做的登录直接 login 这个 中间件 是用来全局拦截开启了 MFA 却没有认证的 OIDC, CAS使用第三方库做的登录直接 login
所以只能在 Middleware 中控制 所以只能在 Middleware 中控制
""" """
def __init__(self, get_response): def __init__(self, get_response):
self.get_response = get_response self.get_response = get_response
@ -42,6 +47,43 @@ class MFAMiddleware:
return redirect(url) return redirect(url)
class ThirdPartyLoginMiddleware(mixins.AuthMixin):
"""OpenID、CAS、SAML2登录规则设置验证"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
# 没有认证过,证明不是从 第三方 来的
if request.user.is_anonymous:
return response
if not request.session.get('auth_third_party_required'):
return response
ip = get_request_ip(request)
try:
self._check_login_acl(request.user, ip)
except Exception as e:
auth_logout(request)
context = {
'title': _('Authentication failed'),
'message': _('Authentication failed (before login check failed): {}').format(e),
'interval': 10,
'redirect_url': reverse('authentication:login'),
'auto_redirect': True,
}
response = render(request, 'authentication/auth_fail_flash_message_standalone.html', context)
else:
guard_url = reverse('authentication:login-guard')
args = request.META.get('QUERY_STRING', '')
if args:
guard_url = "%s?%s" % (guard_url, args)
response = redirect(guard_url)
finally:
request.session.pop('auth_third_party_required', '')
return response
class SessionCookieMiddleware(MiddlewareMixin): class SessionCookieMiddleware(MiddlewareMixin):
@staticmethod @staticmethod

View File

@ -6,6 +6,7 @@ from django.core.cache import cache
from django.dispatch import receiver from django.dispatch import receiver
from django_cas_ng.signals import cas_user_authenticated from django_cas_ng.signals import cas_user_authenticated
from apps.jumpserver.settings.auth import AUTHENTICATION_BACKENDS_THIRD_PARTY
from authentication.backends.oidc.signals import ( from authentication.backends.oidc.signals import (
openid_user_login_failed, openid_user_login_success openid_user_login_failed, openid_user_login_success
) )
@ -28,7 +29,8 @@ def on_user_auth_login_success(sender, user, request, **kwargs):
and user.mfa_enabled \ and user.mfa_enabled \
and not request.session.get('auth_mfa'): and not request.session.get('auth_mfa'):
request.session['auth_mfa_required'] = 1 request.session['auth_mfa_required'] = 1
if request.session.get('auth_backend') in AUTHENTICATION_BACKENDS_THIRD_PARTY:
request.session['auth_third_party_required'] = 1
# 单点登录,超过了自动退出 # 单点登录,超过了自动退出
if settings.USER_LOGIN_SINGLE_MACHINE_ENABLED: if settings.USER_LOGIN_SINGLE_MACHINE_ENABLED:
lock_key = 'single_machine_login_' + str(user.id) lock_key = 'single_machine_login_' + str(user.id)

View File

@ -0,0 +1,70 @@
{% extends '_base_only_content.html' %}
{% load static %}
{% load i18n %}
{% block html_title %} {{ title }} {% endblock %}
{% block title %} {{ title }}{% endblock %}
{% block content %}
<style>
.alert.alert-msg {
background: #F5F5F7;
}
</style>
<div>
<p>
<div class="alert alert-msg" id="messages">
{% if error %}
{{ error }}
{% else %}
{{ message|safe }}
{% endif %}
</div>
</p>
<div class="row">
{% if has_cancel %}
<div class="col-sm-3">
<a href="{{ cancel_url }}" class="btn btn-default block full-width m-b">
{% trans 'Cancel' %}
</a>
</div>
{% endif %}
<div class="col-sm-3">
<a href="{{ redirect_url }}" class="btn btn-primary block full-width m-b">
{% if confirm_button %}
{{ confirm_button }}
{% else %}
{% trans 'Confirm' %}
{% endif %}
</a>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
var message = ''
var time = '{{ interval }}'
{% if error %}
message = '{{ error }}'
{% else %}
message = '{{ message|safe }}'
{% endif %}
function redirect_page() {
if (time >= 0) {
var msg = message + ' <b>' + time + '</b> ...';
$('#messages').html(msg);
time--;
setTimeout(redirect_page, 1000);
} else {
window.location.href = "{{ redirect_url }}";
}
}
{% if auto_redirect %}
window.onload = redirect_page;
{% endif %}
</script>
{% endblock %}

View File

@ -205,6 +205,7 @@ AUTHENTICATION_BACKENDS = [
AUTH_BACKEND_AUTH_TOKEN, AUTH_BACKEND_SSO, AUTH_BACKEND_TEMP_TOKEN AUTH_BACKEND_AUTH_TOKEN, AUTH_BACKEND_SSO, AUTH_BACKEND_TEMP_TOKEN
] ]
AUTHENTICATION_BACKENDS_THIRD_PARTY = [AUTH_BACKEND_OIDC_CODE, AUTH_BACKEND_CAS, AUTH_BACKEND_SAML2]
ONLY_ALLOW_EXIST_USER_AUTH = CONFIG.ONLY_ALLOW_EXIST_USER_AUTH ONLY_ALLOW_EXIST_USER_AUTH = CONFIG.ONLY_ALLOW_EXIST_USER_AUTH
ONLY_ALLOW_AUTH_FROM_SOURCE = CONFIG.ONLY_ALLOW_AUTH_FROM_SOURCE ONLY_ALLOW_AUTH_FROM_SOURCE = CONFIG.ONLY_ALLOW_AUTH_FROM_SOURCE

View File

@ -109,6 +109,7 @@ MIDDLEWARE = [
'authentication.backends.oidc.middleware.OIDCRefreshIDTokenMiddleware', 'authentication.backends.oidc.middleware.OIDCRefreshIDTokenMiddleware',
'authentication.backends.cas.middleware.CASMiddleware', 'authentication.backends.cas.middleware.CASMiddleware',
'authentication.middleware.MFAMiddleware', 'authentication.middleware.MFAMiddleware',
'authentication.middleware.ThirdPartyLoginMiddleware',
'authentication.middleware.SessionCookieMiddleware', 'authentication.middleware.SessionCookieMiddleware',
'simple_history.middleware.HistoryRequestMiddleware', 'simple_history.middleware.HistoryRequestMiddleware',
] ]