perf: 优化登录

pull/8457/head
ibuler 2022-06-20 19:22:48 +08:00
parent 379c7198da
commit 8b819f3779
7 changed files with 129 additions and 103 deletions

View File

@ -52,6 +52,8 @@ class JMSBaseAuthBackend:
logger.debug(info) logger.debug(info)
return allow return allow
from redis_lock.django_cache import RedisCache
from redis import StrictRedis
class JMSModelBackend(JMSBaseAuthBackend, ModelBackend): class JMSModelBackend(JMSBaseAuthBackend, ModelBackend):
pass pass

View File

@ -87,11 +87,11 @@
} }
.jms-title { .jms-title {
padding: 40px 10px 10px; padding: 60px 10px 10px 60px;
} }
.no-captcha-challenge .jms-title { .no-captcha-challenge .jms-title {
padding: 60px 10px 10px; padding: 60px 10px 10px 60px;
} }
.no-captcha-challenge .welcome-message { .no-captcha-challenge .welcome-message {
@ -125,15 +125,27 @@
font-weight: 350 !important; font-weight: 350 !important;
min-height: auto !important; min-height: auto !important;
} }
.right-image {
height: 100%;
width: 100%
}
.jms-title {
font-size: 21px;
font-weight:400;
color: #151515;
letter-spacing: 0;
text-align: left;
}
</style> </style>
</head> </head>
<body> <body>
<div class="login-content"> <div class="login-content">
<div class="right-image-box"> <div class="right-image-box">
<a href="{% if not XPACK_ENABLED %}https://github.com/jumpserver/jumpserver{% endif %}"> <a href="{% if not XPACK_ENABLED %}https://github.com/jumpserver/jumpserver.git{% endif %}">
<img src="{{ LOGIN_IMAGE_URL }}" style="height: 100%; width: 100%"/> <img src="{{ LOGIN_IMAGE_URL }}" class="right-image" alt="screen-image"/>
</a> </a>
</div> </div>
<div class="left-form-box {% if not form.challenge and not form.captcha %} no-captcha-challenge {% endif %}"> <div class="left-form-box {% if not form.challenge and not form.captcha %} no-captcha-challenge {% endif %}">
@ -142,26 +154,23 @@
<li class="dropdown"> <li class="dropdown">
<a class="dropdown-toggle login-page-language" data-toggle="dropdown" href="#" target="_blank"> <a class="dropdown-toggle login-page-language" data-toggle="dropdown" href="#" target="_blank">
<i class="fa fa-globe fa-lg" style="margin-right: 2px"></i> <i class="fa fa-globe fa-lg" style="margin-right: 2px"></i>
{% if request.COOKIES.django_language == 'en' %} <span>{{ current_lang.title }}<b class="caret"></b></span>
<span>English<b class="caret"></b></span>
{% elif request.COOKIES.django_language == 'ja' %}
<span>日本語<b class="caret"></b></span>
{% else %}
<span>中文(简体)<b class="caret"></b></span>
{% endif %}
</a> </a>
<ul class="dropdown-menu profile-dropdown dropdown-menu-right"> <ul class="dropdown-menu profile-dropdown dropdown-menu-right">
<li> <a id="switch_cn" href="{% url 'i18n-switch' lang='zh-hans' %}"> <span>中文(简体)</span> </a> </li> {% for lang in langs %}
<li> <a id="switch_en" href="{% url 'i18n-switch' lang='en' %}"> <span>English</span> </a> </li> <li>
<li> <a id="switch_ja" href="{% url 'i18n-switch' lang='ja' %}"> <span>日本語</span> </a> </li> <a href="{% url 'i18n-switch' lang=lang.code %}">
<span>{{ lang.title }}</span>
</a>
</li>
{% endfor %}
</ul> </ul>
</li> </li>
</ul> </ul>
<div class="jms-title"> <div class="jms-title">
<span style="font-size: 21px;font-weight:400;color: #151515;letter-spacing: 0;">{{ JMS_TITLE }}</span> <span style="">{% trans 'Login' %}</span>
</div> </div>
<div class="contact-form col-md-10 col-md-offset-1"> <div class="contact-form col-md-10 col-md-offset-1">
<form id="login-form" action="" method="post" role="form" novalidate="novalidate"> <form id="login-form" action="" method="post" role="form" novalidate="novalidate">
{% csrf_token %} {% csrf_token %}
<div style="line-height: 17px;margin-bottom: 20px;color: #999999;"> <div style="line-height: 17px;margin-bottom: 20px;color: #999999;">
@ -177,7 +186,6 @@
</div> </div>
{% bootstrap_field form.username show_label=False %} {% bootstrap_field form.username show_label=False %}
<div class="form-group {% if form.password.errors %} has-error {% endif %}"> <div class="form-group {% if form.password.errors %} has-error {% endif %}">
<input type="password" class="form-control" id="password" placeholder="{% trans 'Password' %}" required> <input type="password" class="form-control" id="password" placeholder="{% trans 'Password' %}" required>
<input id="password-hidden" type="text" style="display:none" name="{{ form.password.html_name }}"> <input id="password-hidden" type="text" style="display:none" name="{{ form.password.html_name }}">

View File

@ -10,8 +10,7 @@ from django.contrib.auth import login as auth_login, logout as auth_logout
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import reverse, redirect from django.shortcuts import reverse, redirect
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.db import transaction from django.utils.translation import ugettext as _, get_language
from django.utils.translation import ugettext as _
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_protect
from django.views.decorators.debug import sensitive_post_parameters from django.views.decorators.debug import sensitive_post_parameters
@ -181,6 +180,29 @@ class UserLoginView(mixins.AuthMixin, FormView):
] ]
return [method for method in auth_methods if method['enabled']] return [method for method in auth_methods if method['enabled']]
@staticmethod
def get_support_langs():
langs = [
{
'title': '中文(简体)',
'code': 'zh-hans'
},
{
'title': 'English',
'code': 'en'
},
{
'title': '日本語',
'code': 'ja'
}
]
return langs
def get_current_lang(self):
langs = self.get_support_langs()
matched_lang = filter(lambda x: x['code'] == get_language(), langs)
return next(matched_lang, langs[0])
@staticmethod @staticmethod
def get_forgot_password_url(): def get_forgot_password_url():
forgot_password_url = reverse('authentication:forgot-password') forgot_password_url = reverse('authentication:forgot-password')
@ -191,6 +213,8 @@ class UserLoginView(mixins.AuthMixin, FormView):
context = { context = {
'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(),
'langs': self.get_support_langs(),
'current_lang': self.get_current_lang(),
'forgot_password_url': self.get_forgot_password_url(), 'forgot_password_url': self.get_forgot_password_url(),
**self.get_user_mfa_context(self.request.user) **self.get_user_mfa_context(self.request.user)
} }

View File

@ -13,6 +13,7 @@ from itertools import chain
import paramiko import paramiko
import sshpubkeys import sshpubkeys
from itsdangerous import ( from itsdangerous import (
TimedSerializer,
TimedJSONWebSignatureSerializer, JSONWebSignatureSerializer, TimedJSONWebSignatureSerializer, JSONWebSignatureSerializer,
BadSignature, SignatureExpired BadSignature, SignatureExpired
) )

View File

@ -148,19 +148,8 @@ SESSION_EXPIRE_AT_BROWSER_CLOSE = True
# 自定义的配置SESSION_EXPIRE_AT_BROWSER_CLOSE 始终为 True, 下面这个来控制是否强制关闭后过期 cookie # 自定义的配置SESSION_EXPIRE_AT_BROWSER_CLOSE 始终为 True, 下面这个来控制是否强制关闭后过期 cookie
SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE = CONFIG.SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE = CONFIG.SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE
SESSION_SAVE_EVERY_REQUEST = CONFIG.SESSION_SAVE_EVERY_REQUEST SESSION_SAVE_EVERY_REQUEST = CONFIG.SESSION_SAVE_EVERY_REQUEST
SESSION_ENGINE = 'jumpserver.rewriting.session' SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_REDIS = { SESSION_CACHE_ALIAS = "default"
'url': '%(protocol)s://:%(password)s@%(host)s:%(port)s/%(db)s' % {
'protocol': 'rediss' if CONFIG.REDIS_USE_SSL else 'redis',
'password': CONFIG.REDIS_PASSWORD,
'host': CONFIG.REDIS_HOST,
'port': CONFIG.REDIS_PORT,
'db': CONFIG.REDIS_DB_CACHE,
},
'prefix': 'auth_session',
'socket_timeout': 1,
'retry_on_timeout': False
}
MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage' MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'
# Database # Database
@ -283,7 +272,6 @@ REDIS_SSL_REQUIRED = CONFIG.REDIS_SSL_REQUIRED or 'none'
CACHES = { CACHES = {
'default': { 'default': {
# 'BACKEND': 'redis_cache.RedisCache',
'BACKEND': 'redis_lock.django_cache.RedisCache', 'BACKEND': 'redis_lock.django_cache.RedisCache',
'LOCATION': '%(protocol)s://:%(password)s@%(host)s:%(port)s/%(db)s' % { 'LOCATION': '%(protocol)s://:%(password)s@%(host)s:%(port)s/%(db)s' % {
'protocol': 'rediss' if CONFIG.REDIS_USE_SSL else 'redis', 'protocol': 'rediss' if CONFIG.REDIS_USE_SSL else 'redis',

View File

@ -153,3 +153,5 @@ ANSIBLE_LOG_DIR = os.path.join(PROJECT_DIR, 'data', 'ansible')
REDIS_HOST = CONFIG.REDIS_HOST REDIS_HOST = CONFIG.REDIS_HOST
REDIS_PORT = CONFIG.REDIS_PORT REDIS_PORT = CONFIG.REDIS_PORT
REDIS_PASSWORD = CONFIG.REDIS_PASSWORD REDIS_PASSWORD = CONFIG.REDIS_PASSWORD
DJANGO_REDIS_SCAN_ITERSIZE = 1000

View File

@ -3,9 +3,9 @@ ansible==2.10.7
asn1crypto==0.24.0 asn1crypto==0.24.0
bcrypt==3.1.4 bcrypt==3.1.4
billiard==3.6.4.0 billiard==3.6.4.0
boto3==1.18.11 boto3==1.24.12
botocore==1.21.11 botocore==1.27.12
celery==5.2.2 celery==5.2.7
certifi==2018.1.18 certifi==2018.1.18
cffi==1.13.2 cffi==1.13.2
chardet==3.0.4 chardet==3.0.4
@ -17,117 +17,118 @@ decorator==4.1.2
Django==3.1.14 Django==3.1.14
django-auth-ldap==2.2.0 django-auth-ldap==2.2.0
django-bootstrap3==14.2.0 django-bootstrap3==14.2.0
django-celery-beat==2.2.1 django-celery-beat==2.3.0
django-filter==2.4.0 django-filter==2.4.0
django-formtools==2.2 django-formtools==2.2
django-ranged-response==0.2.0 django-ranged-response==0.2.0
django-rest-swagger==2.2.0 django-rest-swagger==2.2.0
django-simple-captcha==0.5.13 django-simple-captcha==0.5.17
django-timezone-field==4.1.0 django-timezone-field==5.0
djangorestframework==3.12.2 djangorestframework==3.13.1
djangorestframework-bulk==0.2.1 djangorestframework-bulk==0.2.1
docutils==0.14 docutils==0.14
ecdsa==0.13.3 ecdsa==0.13.3
enum-compat==0.0.2 enum-compat==0.0.2
ephem==3.7.6.0 ephem==3.7.6.0
eventlet==0.31.1 eventlet==0.33.1
future==0.16.0 future==0.16.0
ForgeryPy3==0.3.1 ForgeryPy3==0.3.1
greenlet==0.4.14 greenlet==1.1.2
gunicorn==19.9.0 gunicorn==20.1.0
idna==2.6 idna==2.6
itsdangerous==0.24 itsdangerous==1.1.0
itypes==1.1.0 itypes==1.2.0
Jinja2==2.11.3 Jinja2==3.1.2
jmespath==0.9.3 jmespath==1.0.1
kombu==5.2.2 kombu==5.2.4
ldap3==2.4 ldap3==2.9.1
MarkupSafe==1.1.1 MarkupSafe==2.1.1
mysqlclient==2.0.1 mysqlclient==2.1.0
olefile==0.44 olefile==0.46
openapi-codec==1.3.2 openapi-codec==1.3.2
paramiko==2.10.1 paramiko==2.11.0
passlib==1.7.1 passlib==1.7.4
Pillow==9.0.1 Pillow==9.1.1
pyasn1==0.4.8 pyasn1==0.4.8
pycparser==2.19 pycparser==2.21
pycryptodome==3.12.0 pycryptodome==3.14.1
pycryptodomex==3.12.0 pycryptodomex==3.14.1
pyotp==2.2.6 pyotp==2.6.0
PyNaCl==1.5.0 PyNaCl==1.5.0
python-dateutil==2.8.2 python-dateutil==2.8.2
pytz==2018.3 pytz==2022.1
PyYAML==6.0 PyYAML==6.0
redis==4.3.1 redis==4.3.3
requests==2.25.1 requests==2.28.0
jms-storage==0.0.42 # jms-storage==0.0.42
s3transfer==0.5.0 s3transfer==0.6.0
simplejson==3.13.2 simplejson==3.17.6
six==1.11.0 six==1.16.0
sshpubkeys==3.1.0 sshpubkeys==3.3.1
uritemplate==3.0.0 uritemplate==4.1.1
urllib3==1.26.5 urllib3==1.26.9
vine==5.0.0 vine==5.0.0
drf-yasg==1.20.0 drf-yasg==1.20.0
Werkzeug==0.15.3 Werkzeug==2.1.2
drf-nested-routers==0.91 drf-nested-routers==0.93.4
aliyun-python-sdk-core-v3==2.9.1
aliyun-python-sdk-ecs==4.10.1
rest_condition==1.0.3 rest_condition==1.0.3
python-ldap==3.4.0 python-ldap==3.4.0
tencentcloud-sdk-python==3.0.477 django-radius==1.5.0
django-radius==1.4.0
django-redis-sessions==0.6.1
unicodecsv==0.14.1 unicodecsv==0.14.1
python-daemon==2.2.3 python-daemon==2.3.0
httpsig==1.3.0 httpsig==1.3.0
treelib==1.5.3 treelib==1.6.1
django-proxy==1.2.1 django-proxy==1.2.1
flower==1.0.0 flower==1.0.0
channels-redis==3.2.0 channels-redis==3.4.0
channels==2.4.0 channels==3.0.4
daphne==2.4.1 daphne==3.0.2
psutil==5.6.6 psutil==5.9.1
django-cas-ng==4.0.1 django-cas-ng==4.0.1
python-cas==1.5.0 python-cas==1.5.0
ipython ipython
huaweicloud-sdk-python==1.0.21 django-redis==5.2.0
django-redis==4.11.0
python-redis-lock==3.7.0 python-redis-lock==3.7.0
jumpserver-django-oidc-rp==0.3.7.8 jumpserver-django-oidc-rp==0.3.7.8
django-mysql==3.9.0 django-mysql==3.9.0
gmssl==3.2.1 gmssl==3.2.1
azure-mgmt-compute==4.6.2
azure-mgmt-network==2.7.0
msrestazure==0.6.4 msrestazure==0.6.4
adal==1.2.5 adal==1.2.5
openpyxl==3.0.5 openpyxl==3.0.10
pyexcel==0.6.6 pyexcel==0.7.0
pyexcel-xlsx==0.6.0 pyexcel-xlsx==0.6.0
data-tree==0.0.1 data-tree==0.0.1
pyvmomi==7.0.1 pyvmomi==7.0.1
termcolor==1.1.0 termcolor==1.1.0
azure-identity==1.5.0 django-simple-history==3.1.1
azure-mgmt-subscription==1.0.0 geoip2==4.5.0
qingcloud-sdk==1.2.12
django-simple-history==3.0.0
google-cloud-compute==0.5.0
PyMySQL==1.0.2
cx-Oracle==8.2.1
psycopg2-binary==2.9.1
alibabacloud_dysmsapi20170525==2.0.2
geoip2==4.4.0
html2text==2020.1.16 html2text==2020.1.16
python-novaclient==11.0.1
pyzipper==0.3.5 pyzipper==0.3.5
python3-saml==1.12.0 python3-saml==1.12.0
python-keystoneclient==4.3.0
pymssql==2.1.5
kubernetes==21.7.0 kubernetes==21.7.0
websocket-client==1.2.3 websocket-client==1.2.3
numpy==1.22.0 numpy==1.22.0
pandas==1.3.5 pandas==1.3.5
pyjwkest==1.4.2 pyjwkest==1.4.2
jsonfield2==4.0.0.post0 jsonfield2==4.0.0.post0
bce-python-sdk==0.8.64
ipip-ipdb==1.6.1 ipip-ipdb==1.6.1
# Cloud req
qingcloud-sdk==1.2.12
azure-mgmt-subscription==1.0.0
azure-identity==1.5.0
azure-mgmt-compute==4.6.2
azure-mgmt-network==2.7.0
google-cloud-compute==0.5.0
alibabacloud_dysmsapi20170525==2.0.2
python-novaclient==11.0.1
python-keystoneclient==4.3.0
bce-python-sdk==0.8.64
tencentcloud-sdk-python==3.0.477
aliyun-python-sdk-core-v3==2.9.1
aliyun-python-sdk-ecs==4.10.1
huaweicloud-sdk-python==1.0.21
# DB requirements
PyMySQL==1.0.2
cx-Oracle==8.2.1
psycopg2-binary==2.9.1
pymssql==2.1.5