mirror of https://github.com/jumpserver/jumpserver
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
parent
c295f1451a
commit
3951b8b080
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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',
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue