mirror of https://github.com/jumpserver/jumpserver
parent
b2d9670721
commit
4315cbe6d0
|
@ -232,11 +232,11 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
{% if not origin_is_allowed %}
|
{% if error_origin %}
|
||||||
<div class='alert alert-danger error-info'>
|
<div class='alert alert-danger error-info'>
|
||||||
配置文件存在问题,无法完成登录,请联系管理员解决,或查看最新更新说明 <br/>
|
配置文件存在问题,无法完成登录,请联系管理员解决,或查看最新更新说明 <br/>
|
||||||
Configuration file has problems and cannot be logged in. Please contact the administrator <br/>
|
Configuration file has problems and cannot be logged in. Please contact the administrator <br/>
|
||||||
- {{ origin }} -
|
- {{ error_origin }} -
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="login-content extra-fields-{{ extra_fields_count }}">
|
<div class="login-content extra-fields-{{ extra_fields_count }}">
|
||||||
|
@ -321,8 +321,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<button type="submit" class="btn btn-transparent" onclick="doLogin();return false;"
|
<button type="submit" class="btn btn-transparent" onclick="doLogin();return false;">
|
||||||
{% if not origin_is_allowed %} disabled {% endif %}>
|
|
||||||
{% trans 'Login' %}
|
{% trans 'Login' %}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,6 +6,7 @@ from __future__ import unicode_literals
|
||||||
import datetime
|
import datetime
|
||||||
import os
|
import os
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import BACKEND_SESSION_KEY
|
from django.contrib.auth import BACKEND_SESSION_KEY
|
||||||
|
@ -18,7 +19,7 @@ from django.urls import reverse_lazy
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from django.utils.translation import gettext as _, get_language
|
from django.utils.translation import gettext as _, get_language
|
||||||
from django.views.decorators.cache import never_cache
|
from django.views.decorators.cache import never_cache
|
||||||
from django.views.decorators.csrf import csrf_protect
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.views.decorators.debug import sensitive_post_parameters
|
from django.views.decorators.debug import sensitive_post_parameters
|
||||||
from django.views.generic.base import TemplateView, RedirectView
|
from django.views.generic.base import TemplateView, RedirectView
|
||||||
from django.views.generic.edit import FormView
|
from django.views.generic.edit import FormView
|
||||||
|
@ -40,6 +41,7 @@ __all__ = [
|
||||||
class UserLoginContextMixin:
|
class UserLoginContextMixin:
|
||||||
get_user_mfa_context: Callable
|
get_user_mfa_context: Callable
|
||||||
request: HttpRequest
|
request: HttpRequest
|
||||||
|
error_origin: str
|
||||||
|
|
||||||
def get_support_auth_methods(self):
|
def get_support_auth_methods(self):
|
||||||
auth_methods = [
|
auth_methods = [
|
||||||
|
@ -134,19 +136,8 @@ class UserLoginContextMixin:
|
||||||
count += 1
|
count += 1
|
||||||
return count
|
return count
|
||||||
|
|
||||||
def origin_is_allowed(self):
|
|
||||||
from urllib.parse import urlparse
|
|
||||||
http_referer = self.request.META.get('HTTP_REFERER')
|
|
||||||
try:
|
|
||||||
referer = urlparse(http_referer)
|
|
||||||
except ValueError:
|
|
||||||
return False, None
|
|
||||||
allowed_domains = settings.ALLOWED_DOMAINS
|
|
||||||
return referer.netloc in allowed_domains, referer.netloc
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
origin_allowed, origin = self.origin_is_allowed()
|
|
||||||
context.update({
|
context.update({
|
||||||
'demo_mode': os.environ.get("DEMO_MODE"),
|
'demo_mode': os.environ.get("DEMO_MODE"),
|
||||||
'auth_methods': self.get_support_auth_methods(),
|
'auth_methods': self.get_support_auth_methods(),
|
||||||
|
@ -154,19 +145,19 @@ class UserLoginContextMixin:
|
||||||
'current_lang': self.get_current_lang(),
|
'current_lang': self.get_current_lang(),
|
||||||
'forgot_password_url': self.get_forgot_password_url(),
|
'forgot_password_url': self.get_forgot_password_url(),
|
||||||
'extra_fields_count': self.get_extra_fields_count(context),
|
'extra_fields_count': self.get_extra_fields_count(context),
|
||||||
'origin_is_allowed': origin_allowed,
|
'error_origin': self.error_origin,
|
||||||
'origin': origin,
|
|
||||||
**self.get_user_mfa_context(self.request.user)
|
**self.get_user_mfa_context(self.request.user)
|
||||||
})
|
})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
@method_decorator(sensitive_post_parameters(), name='dispatch')
|
@method_decorator(sensitive_post_parameters(), name='dispatch')
|
||||||
@method_decorator(csrf_protect, name='dispatch')
|
|
||||||
@method_decorator(never_cache, name='dispatch')
|
@method_decorator(never_cache, name='dispatch')
|
||||||
|
@method_decorator(csrf_exempt, name='dispatch')
|
||||||
class UserLoginView(mixins.AuthMixin, UserLoginContextMixin, FormView):
|
class UserLoginView(mixins.AuthMixin, UserLoginContextMixin, FormView):
|
||||||
redirect_field_name = 'next'
|
redirect_field_name = 'next'
|
||||||
template_name = 'authentication/login.html'
|
template_name = 'authentication/login.html'
|
||||||
|
error_origin = ''
|
||||||
|
|
||||||
def redirect_third_party_auth_if_need(self, request):
|
def redirect_third_party_auth_if_need(self, request):
|
||||||
# show jumpserver login page if request http://{JUMP-SERVER}/?admin=1
|
# show jumpserver login page if request http://{JUMP-SERVER}/?admin=1
|
||||||
|
@ -215,11 +206,32 @@ class UserLoginView(mixins.AuthMixin, UserLoginContextMixin, FormView):
|
||||||
request.session.set_test_cookie()
|
request.session.set_test_cookie()
|
||||||
return super().get(request, *args, **kwargs)
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def check_origin_is_allowed(self, request):
|
||||||
|
http_referer = request.META.get('HTTP_REFERER')
|
||||||
|
if not http_referer:
|
||||||
|
return False, ''
|
||||||
|
referer = urlparse(http_referer)
|
||||||
|
netloc = str(referer.netloc)
|
||||||
|
allowed_domains = settings.ALLOWED_DOMAINS
|
||||||
|
allowed = netloc in allowed_domains
|
||||||
|
|
||||||
|
if not allowed and ':' not in netloc:
|
||||||
|
suffix = ':80' if referer.scheme == 'http' else ':443'
|
||||||
|
netloc += suffix
|
||||||
|
allowed = netloc in allowed_domains
|
||||||
|
return allowed, netloc
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
if not self.request.session.test_cookie_worked():
|
if not self.request.session.test_cookie_worked():
|
||||||
form.add_error(None, _("Login timeout, please try again."))
|
form.add_error(None, _("Login timeout, please try again."))
|
||||||
return self.form_invalid(form)
|
return self.form_invalid(form)
|
||||||
|
|
||||||
|
origin_allowed, origin = self.check_origin_is_allowed(self.request)
|
||||||
|
if not origin_allowed:
|
||||||
|
self.error_origin = origin
|
||||||
|
form.add_error(None, '当前域不在信任域中,拒绝登录')
|
||||||
|
return self.form_invalid(form)
|
||||||
|
|
||||||
# https://docs.djangoproject.com/en/3.1/topics/http/sessions/#setting-test-cookies
|
# https://docs.djangoproject.com/en/3.1/topics/http/sessions/#setting-test-cookies
|
||||||
self.request.session.delete_test_cookie()
|
self.request.session.delete_test_cookie()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue