mirror of https://github.com/jumpserver/jumpserver
perf: Client login
parent
3cd68ba0a9
commit
7a9a71197a
|
@ -1,12 +1,13 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
from django.urls import path
|
|
||||||
import django_cas_ng.views
|
import django_cas_ng.views
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
from .views import CASLoginView
|
from .views import CASLoginView, CASCallbackClientView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('login/', CASLoginView.as_view(), name='cas-login'),
|
path('login/', CASLoginView.as_view(), name='cas-login'),
|
||||||
path('logout/', django_cas_ng.views.LogoutView.as_view(), name='cas-logout'),
|
path('logout/', django_cas_ng.views.LogoutView.as_view(), name='cas-logout'),
|
||||||
path('callback/', django_cas_ng.views.CallbackView.as_view(), name='cas-proxy-callback'),
|
path('callback/', django_cas_ng.views.CallbackView.as_view(), name='cas-proxy-callback'),
|
||||||
|
path('login/client', CASCallbackClientView.as_view(), name='cas-proxy-callback-client'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
from django_cas_ng.views import LoginView
|
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.views.generic import View
|
||||||
|
from django_cas_ng.views import LoginView
|
||||||
|
|
||||||
__all__ = ['LoginView']
|
__all__ = ['LoginView']
|
||||||
|
|
||||||
|
from authentication.views.utils import redirect_to_guard_view
|
||||||
|
|
||||||
|
|
||||||
class CASLoginView(LoginView):
|
class CASLoginView(LoginView):
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
|
@ -13,3 +16,8 @@ class CASLoginView(LoginView):
|
||||||
return HttpResponseRedirect('/')
|
return HttpResponseRedirect('/')
|
||||||
|
|
||||||
|
|
||||||
|
class CASCallbackClientView(View):
|
||||||
|
http_method_names = ['get', ]
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
return redirect_to_guard_view(query_string='next=client')
|
||||||
|
|
|
@ -4,9 +4,9 @@ from django.urls import path
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('login/', views.OAuth2AuthRequestView.as_view(), name='login'),
|
path('login/', views.OAuth2AuthRequestView.as_view(), name='login'),
|
||||||
path('callback/', views.OAuth2AuthCallbackView.as_view(), name='login-callback'),
|
path('callback/', views.OAuth2AuthCallbackView.as_view(), name='login-callback'),
|
||||||
|
path('callback/client/', views.OAuth2AuthCallbackClientView.as_view(), name='login-callback-client'),
|
||||||
path('logout/', views.OAuth2EndSessionView.as_view(), name='logout')
|
path('logout/', views.OAuth2EndSessionView.as_view(), name='logout')
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
from django.views import View
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import auth
|
from django.contrib import auth
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.http import urlencode
|
from django.utils.http import urlencode
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
|
from authentication.mixins import authenticate
|
||||||
from authentication.utils import build_absolute_uri
|
from authentication.utils import build_absolute_uri
|
||||||
from authentication.views.mixins import FlashMessageMixin
|
from authentication.views.mixins import FlashMessageMixin
|
||||||
from authentication.mixins import authenticate
|
from authentication.views.utils import redirect_to_guard_view
|
||||||
from common.utils import get_logger
|
from common.utils import get_logger
|
||||||
|
|
||||||
|
|
||||||
logger = get_logger(__file__)
|
logger = get_logger(__file__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,6 +67,13 @@ class OAuth2AuthCallbackView(View, FlashMessageMixin):
|
||||||
return HttpResponseRedirect(redirect_url)
|
return HttpResponseRedirect(redirect_url)
|
||||||
|
|
||||||
|
|
||||||
|
class OAuth2AuthCallbackClientView(View):
|
||||||
|
http_method_names = ['get', ]
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
return redirect_to_guard_view(query_string='next=client')
|
||||||
|
|
||||||
|
|
||||||
class OAuth2EndSessionView(View):
|
class OAuth2EndSessionView(View):
|
||||||
http_method_names = ['get', 'post', ]
|
http_method_names = ['get', 'post', ]
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,9 @@ from django.urls import path
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('login/', views.OIDCAuthRequestView.as_view(), name='login'),
|
path('login/', views.OIDCAuthRequestView.as_view(), name='login'),
|
||||||
path('callback/', views.OIDCAuthCallbackView.as_view(), name='login-callback'),
|
path('callback/', views.OIDCAuthCallbackView.as_view(), name='login-callback'),
|
||||||
|
path('callback/client/', views.OIDCAuthCallbackClientView.as_view(), name='login-callback-client'),
|
||||||
path('logout/', views.OIDCEndSessionView.as_view(), name='logout'),
|
path('logout/', views.OIDCEndSessionView.as_view(), name='logout'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -22,13 +22,14 @@ from django.http import HttpResponseRedirect, QueryDict
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.crypto import get_random_string
|
from django.utils.crypto import get_random_string
|
||||||
from django.utils.http import urlencode
|
from django.utils.http import urlencode
|
||||||
from django.views.generic import View
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.views.generic import View
|
||||||
|
|
||||||
from authentication.utils import build_absolute_uri_for_oidc
|
from authentication.utils import build_absolute_uri_for_oidc
|
||||||
from authentication.views.mixins import FlashMessageMixin
|
from authentication.views.mixins import FlashMessageMixin
|
||||||
from common.utils import safe_next_url
|
from common.utils import safe_next_url
|
||||||
from .utils import get_logger
|
from .utils import get_logger
|
||||||
|
from ...views.utils import redirect_to_guard_view
|
||||||
|
|
||||||
logger = get_logger(__file__)
|
logger = get_logger(__file__)
|
||||||
|
|
||||||
|
@ -208,6 +209,13 @@ class OIDCAuthCallbackView(View, FlashMessageMixin):
|
||||||
return HttpResponseRedirect(settings.AUTH_OPENID_AUTHENTICATION_FAILURE_REDIRECT_URI)
|
return HttpResponseRedirect(settings.AUTH_OPENID_AUTHENTICATION_FAILURE_REDIRECT_URI)
|
||||||
|
|
||||||
|
|
||||||
|
class OIDCAuthCallbackClientView(View):
|
||||||
|
http_method_names = ['get', ]
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
return redirect_to_guard_view(query_string='next=client')
|
||||||
|
|
||||||
|
|
||||||
class OIDCEndSessionView(View):
|
class OIDCEndSessionView(View):
|
||||||
""" Allows to end the session of any user authenticated using OpenID Connect.
|
""" Allows to end the session of any user authenticated using OpenID Connect.
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,10 @@ from django.urls import path
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('login/', views.Saml2AuthRequestView.as_view(), name='saml2-login'),
|
path('login/', views.Saml2AuthRequestView.as_view(), name='saml2-login'),
|
||||||
path('logout/', views.Saml2EndSessionView.as_view(), name='saml2-logout'),
|
path('logout/', views.Saml2EndSessionView.as_view(), name='saml2-logout'),
|
||||||
path('callback/', views.Saml2AuthCallbackView.as_view(), name='saml2-callback'),
|
path('callback/', views.Saml2AuthCallbackView.as_view(), name='saml2-callback'),
|
||||||
|
path('callback/client/', views.Saml2AuthCallbackClientView.as_view(), name='saml2-callback-client'),
|
||||||
path('metadata/', views.Saml2AuthMetadataView.as_view(), name='saml2-metadata'),
|
path('metadata/', views.Saml2AuthMetadataView.as_view(), name='saml2-metadata'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -19,6 +19,7 @@ from onelogin.saml2.idp_metadata_parser import (
|
||||||
from authentication.views.mixins import FlashMessageMixin
|
from authentication.views.mixins import FlashMessageMixin
|
||||||
from common.utils import get_logger
|
from common.utils import get_logger
|
||||||
from .settings import JmsSaml2Settings
|
from .settings import JmsSaml2Settings
|
||||||
|
from ...views.utils import redirect_to_guard_view
|
||||||
|
|
||||||
logger = get_logger(__file__)
|
logger = get_logger(__file__)
|
||||||
|
|
||||||
|
@ -298,6 +299,13 @@ class Saml2AuthCallbackView(View, PrepareRequestMixin, FlashMessageMixin):
|
||||||
return super().dispatch(*args, **kwargs)
|
return super().dispatch(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class Saml2AuthCallbackClientView(View):
|
||||||
|
http_method_names = ['get', ]
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
return redirect_to_guard_view(query_string='next=client')
|
||||||
|
|
||||||
|
|
||||||
class Saml2AuthMetadataView(View, PrepareRequestMixin):
|
class Saml2AuthMetadataView(View, PrepareRequestMixin):
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
|
|
|
@ -110,6 +110,9 @@ class BaseLoginCallbackView(AuthMixin, FlashMessageMixin, IMClientMixin, View):
|
||||||
msg = e.msg
|
msg = e.msg
|
||||||
response = self.get_failed_response(login_url, title=msg, msg=msg)
|
response = self.get_failed_response(login_url, title=msg, msg=msg)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
if 'next=client' in redirect_url:
|
||||||
|
self.request.META['QUERY_STRING'] += '&next=client'
|
||||||
return self.redirect_to_guard_view()
|
return self.redirect_to_guard_view()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -175,6 +175,8 @@ class DingTalkQRLoginView(DingTalkQRMixin, METAMixin, View):
|
||||||
|
|
||||||
def get(self, request: HttpRequest):
|
def get(self, request: HttpRequest):
|
||||||
redirect_url = request.GET.get('redirect_url') or reverse('index')
|
redirect_url = request.GET.get('redirect_url') or reverse('index')
|
||||||
|
query_string = request.GET.urlencode()
|
||||||
|
redirect_url = f'{redirect_url}?{query_string}'
|
||||||
next_url = self.get_next_url_from_meta() or reverse('index')
|
next_url = self.get_next_url_from_meta() or reverse('index')
|
||||||
next_url = safe_next_url(next_url, request=request)
|
next_url = safe_next_url(next_url, request=request)
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,8 @@ class FeiShuQRLoginView(FeiShuQRMixin, View):
|
||||||
|
|
||||||
def get(self, request: HttpRequest):
|
def get(self, request: HttpRequest):
|
||||||
redirect_url = request.GET.get('redirect_url') or reverse('index')
|
redirect_url = request.GET.get('redirect_url') or reverse('index')
|
||||||
|
query_string = request.GET.urlencode()
|
||||||
|
redirect_url = f'{redirect_url}?{query_string}'
|
||||||
redirect_uri = reverse(f'authentication:{self.category}-qr-login-callback', external=True)
|
redirect_uri = reverse(f'authentication:{self.category}-qr-login-callback', external=True)
|
||||||
redirect_uri += '?' + urlencode({
|
redirect_uri += '?' + urlencode({
|
||||||
'redirect_url': redirect_url,
|
'redirect_url': redirect_url,
|
||||||
|
|
|
@ -45,69 +45,70 @@ class UserLoginContextMixin:
|
||||||
error_origin: str
|
error_origin: str
|
||||||
|
|
||||||
def get_support_auth_methods(self):
|
def get_support_auth_methods(self):
|
||||||
|
query_string = self.request.GET.urlencode()
|
||||||
auth_methods = [
|
auth_methods = [
|
||||||
{
|
{
|
||||||
'name': 'OpenID',
|
'name': 'OpenID',
|
||||||
'enabled': settings.AUTH_OPENID,
|
'enabled': settings.AUTH_OPENID,
|
||||||
'url': reverse('authentication:openid:login'),
|
'url': f"{reverse('authentication:openid:login')}?{query_string}",
|
||||||
'logo': static('img/login_oidc_logo.png'),
|
'logo': static('img/login_oidc_logo.png'),
|
||||||
'auto_redirect': True # 是否支持自动重定向
|
'auto_redirect': True # 是否支持自动重定向
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'CAS',
|
'name': 'CAS',
|
||||||
'enabled': settings.AUTH_CAS,
|
'enabled': settings.AUTH_CAS,
|
||||||
'url': reverse('authentication:cas:cas-login'),
|
'url': f"{reverse('authentication:cas:cas-login')}?{query_string}",
|
||||||
'logo': static('img/login_cas_logo.png'),
|
'logo': static('img/login_cas_logo.png'),
|
||||||
'auto_redirect': True
|
'auto_redirect': True
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'SAML2',
|
'name': 'SAML2',
|
||||||
'enabled': settings.AUTH_SAML2,
|
'enabled': settings.AUTH_SAML2,
|
||||||
'url': reverse('authentication:saml2:saml2-login'),
|
'url': f"{reverse('authentication:saml2:saml2-login')}?{query_string}",
|
||||||
'logo': static('img/login_saml2_logo.png'),
|
'logo': static('img/login_saml2_logo.png'),
|
||||||
'auto_redirect': True
|
'auto_redirect': True
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': settings.AUTH_OAUTH2_PROVIDER,
|
'name': settings.AUTH_OAUTH2_PROVIDER,
|
||||||
'enabled': settings.AUTH_OAUTH2,
|
'enabled': settings.AUTH_OAUTH2,
|
||||||
'url': reverse('authentication:oauth2:login'),
|
'url': f"{reverse('authentication:oauth2:login')}?{query_string}",
|
||||||
'logo': static_or_direct(settings.AUTH_OAUTH2_LOGO_PATH),
|
'logo': static_or_direct(settings.AUTH_OAUTH2_LOGO_PATH),
|
||||||
'auto_redirect': True
|
'auto_redirect': True
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': _('WeCom'),
|
'name': _('WeCom'),
|
||||||
'enabled': settings.AUTH_WECOM,
|
'enabled': settings.AUTH_WECOM,
|
||||||
'url': reverse('authentication:wecom-qr-login'),
|
'url': f"{reverse('authentication:wecom-qr-login')}?{query_string}",
|
||||||
'logo': static('img/login_wecom_logo.png'),
|
'logo': static('img/login_wecom_logo.png'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': _('DingTalk'),
|
'name': _('DingTalk'),
|
||||||
'enabled': settings.AUTH_DINGTALK,
|
'enabled': settings.AUTH_DINGTALK,
|
||||||
'url': reverse('authentication:dingtalk-qr-login'),
|
'url': f"{reverse('authentication:dingtalk-qr-login')}?{query_string}",
|
||||||
'logo': static('img/login_dingtalk_logo.png')
|
'logo': static('img/login_dingtalk_logo.png')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': _('FeiShu'),
|
'name': _('FeiShu'),
|
||||||
'enabled': settings.AUTH_FEISHU,
|
'enabled': settings.AUTH_FEISHU,
|
||||||
'url': reverse('authentication:feishu-qr-login'),
|
'url': f"{reverse('authentication:feishu-qr-login')}?{query_string}",
|
||||||
'logo': static('img/login_feishu_logo.png')
|
'logo': static('img/login_feishu_logo.png')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': 'Lark',
|
'name': 'Lark',
|
||||||
'enabled': settings.AUTH_LARK,
|
'enabled': settings.AUTH_LARK,
|
||||||
'url': reverse('authentication:lark-qr-login'),
|
'url': f"{reverse('authentication:lark-qr-login')}?{query_string}",
|
||||||
'logo': static('img/login_lark_logo.png')
|
'logo': static('img/login_lark_logo.png')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': _('Slack'),
|
'name': _('Slack'),
|
||||||
'enabled': settings.AUTH_SLACK,
|
'enabled': settings.AUTH_SLACK,
|
||||||
'url': reverse('authentication:slack-qr-login'),
|
'url': f"{reverse('authentication:slack-qr-login')}?{query_string}",
|
||||||
'logo': static('img/login_slack_logo.png')
|
'logo': static('img/login_slack_logo.png')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name': _("Passkey"),
|
'name': _("Passkey"),
|
||||||
'enabled': settings.AUTH_PASSKEY,
|
'enabled': settings.AUTH_PASSKEY,
|
||||||
'url': reverse('api-auth:passkey-login'),
|
'url': f"{reverse('api-auth:passkey-login')}?{query_string}",
|
||||||
'logo': static('img/login_passkey.png')
|
'logo': static('img/login_passkey.png')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -220,7 +221,7 @@ class UserLoginView(mixins.AuthMixin, UserLoginContextMixin, FormView):
|
||||||
'redirect_url': redirect_url,
|
'redirect_url': redirect_url,
|
||||||
'interval': 3,
|
'interval': 3,
|
||||||
'has_cancel': True,
|
'has_cancel': True,
|
||||||
'cancel_url': reverse('authentication:login') + '?admin=1'
|
'cancel_url': reverse('authentication:login') + f'?admin=1&{query_string}'
|
||||||
}
|
}
|
||||||
redirect_url = FlashMessageUtil.gen_message_url(message_data)
|
redirect_url = FlashMessageUtil.gen_message_url(message_data)
|
||||||
return redirect_url
|
return redirect_url
|
||||||
|
@ -306,6 +307,7 @@ class UserLoginGuardView(mixins.AuthMixin, RedirectView):
|
||||||
login_url = reverse_lazy('authentication:login')
|
login_url = reverse_lazy('authentication:login')
|
||||||
login_mfa_url = reverse_lazy('authentication:login-mfa')
|
login_mfa_url = reverse_lazy('authentication:login-mfa')
|
||||||
login_confirm_url = reverse_lazy('authentication:login-wait-confirm')
|
login_confirm_url = reverse_lazy('authentication:login-wait-confirm')
|
||||||
|
query_string = True
|
||||||
|
|
||||||
def format_redirect_url(self, url):
|
def format_redirect_url(self, url):
|
||||||
args = self.request.META.get('QUERY_STRING', '')
|
args = self.request.META.get('QUERY_STRING', '')
|
||||||
|
|
|
@ -2,13 +2,14 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from django.views.generic.edit import FormView
|
|
||||||
from django.shortcuts import redirect, reverse
|
from django.shortcuts import redirect, reverse
|
||||||
|
from django.views.generic.edit import FormView
|
||||||
|
|
||||||
from common.utils import get_logger
|
from common.utils import get_logger
|
||||||
from users.views import UserFaceCaptureView
|
from users.views import UserFaceCaptureView
|
||||||
from .. import forms, errors, mixins
|
|
||||||
from .utils import redirect_to_guard_view
|
from .utils import redirect_to_guard_view
|
||||||
|
from .. import forms, errors, mixins
|
||||||
from ..const import MFAType
|
from ..const import MFAType
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
@ -48,7 +49,8 @@ class UserLoginMFAView(mixins.AuthMixin, FormView):
|
||||||
self._do_check_user_mfa(code, mfa_type)
|
self._do_check_user_mfa(code, mfa_type)
|
||||||
user, ip = self.get_user_from_session(), self.get_request_ip()
|
user, ip = self.get_user_from_session(), self.get_request_ip()
|
||||||
MFABlockUtils(user.username, ip).clean_failed_count()
|
MFABlockUtils(user.username, ip).clean_failed_count()
|
||||||
return redirect_to_guard_view('mfa_ok')
|
query_string = self.request.GET.urlencode()
|
||||||
|
return redirect_to_guard_view('mfa_ok', query_string)
|
||||||
except (errors.MFAFailedError, errors.BlockMFAError) as e:
|
except (errors.MFAFailedError, errors.BlockMFAError) as e:
|
||||||
form.add_error('code', e.msg)
|
form.add_error('code', e.msg)
|
||||||
return super().form_invalid(form)
|
return super().form_invalid(form)
|
||||||
|
|
|
@ -98,6 +98,8 @@ class SlackQRLoginView(SlackMixin, View):
|
||||||
|
|
||||||
def get(self, request: Request):
|
def get(self, request: Request):
|
||||||
redirect_url = request.GET.get('redirect_url') or reverse('index')
|
redirect_url = request.GET.get('redirect_url') or reverse('index')
|
||||||
|
query_string = request.GET.urlencode()
|
||||||
|
redirect_url = f'{redirect_url}?{query_string}'
|
||||||
redirect_uri = reverse('authentication:slack-qr-login-callback', external=True)
|
redirect_uri = reverse('authentication:slack-qr-login-callback', external=True)
|
||||||
redirect_uri += '?' + urlencode({
|
redirect_uri += '?' + urlencode({
|
||||||
'redirect_url': redirect_url,
|
'redirect_url': redirect_url,
|
||||||
|
|
|
@ -1,8 +1,18 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
|
from urllib.parse import urlencode, parse_qsl
|
||||||
|
|
||||||
from django.shortcuts import reverse, redirect
|
from django.shortcuts import reverse, redirect
|
||||||
|
|
||||||
|
|
||||||
def redirect_to_guard_view(comment=''):
|
def redirect_to_guard_view(comment='', query_string=None):
|
||||||
continue_url = reverse('authentication:login-guard') + '?_=' + comment
|
params = {'_': comment}
|
||||||
|
base_url = reverse('authentication:login-guard')
|
||||||
|
|
||||||
|
if query_string:
|
||||||
|
params.update(dict(parse_qsl(query_string)))
|
||||||
|
|
||||||
|
query_string = urlencode(params)
|
||||||
|
|
||||||
|
continue_url = f"{base_url}?{query_string}"
|
||||||
return redirect(continue_url)
|
return redirect(continue_url)
|
||||||
|
|
|
@ -22,7 +22,6 @@ from users.views import UserVerifyPasswordView
|
||||||
from .base import BaseLoginCallbackView, BaseBindCallbackView
|
from .base import BaseLoginCallbackView, BaseBindCallbackView
|
||||||
from .mixins import METAMixin, FlashMessageMixin
|
from .mixins import METAMixin, FlashMessageMixin
|
||||||
|
|
||||||
|
|
||||||
logger = get_logger(__file__)
|
logger = get_logger(__file__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,6 +85,8 @@ class WeComQRBindView(WeComQRMixin, View):
|
||||||
|
|
||||||
def get(self, request: HttpRequest):
|
def get(self, request: HttpRequest):
|
||||||
redirect_url = request.GET.get('redirect_url')
|
redirect_url = request.GET.get('redirect_url')
|
||||||
|
query_string = request.GET.urlencode()
|
||||||
|
redirect_url = f'{redirect_url}?{query_string}'
|
||||||
redirect_uri = reverse('authentication:wecom-qr-bind-callback', external=True)
|
redirect_uri = reverse('authentication:wecom-qr-bind-callback', external=True)
|
||||||
redirect_uri += '?' + urlencode({'redirect_url': redirect_url})
|
redirect_uri += '?' + urlencode({'redirect_url': redirect_url})
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ import time
|
||||||
|
|
||||||
import pyotp
|
import pyotp
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import logout as auth_logout
|
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
|
@ -75,7 +74,6 @@ def redirect_user_first_login_or_index(request, redirect_field_name):
|
||||||
|
|
||||||
if url == 'client':
|
if url == 'client':
|
||||||
url = get_redirect_client_url(request)
|
url = get_redirect_client_url(request)
|
||||||
auth_logout(request)
|
|
||||||
|
|
||||||
url = safe_next_url(url, request=request)
|
url = safe_next_url(url, request=request)
|
||||||
# 防止 next 地址为 None
|
# 防止 next 地址为 None
|
||||||
|
|
Loading…
Reference in New Issue