Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
J
jumpserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
jumpserver
Commits
6700dc96
Commit
6700dc96
authored
Feb 27, 2019
by
BaiJiangJie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Update] users认证逻辑迁移到authentication中
parent
21714cc4
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
263 additions
and
239 deletions
+263
-239
__init__.py
apps/authentication/api/__init__.py
+4
-0
auth.py
apps/authentication/api/auth.py
+200
-0
authentication.py
apps/authentication/authentication.py
+1
-1
api_urls.py
apps/authentication/urls/api_urls.py
+18
-0
view_urls.py
apps/authentication/urls/view_urls.py
+8
-2
__init__.py
apps/authentication/views/__init__.py
+1
-0
login.py
apps/authentication/views/login.py
+14
-19
settings.py
apps/jumpserver/settings.py
+5
-5
urls.py
apps/jumpserver/urls.py
+1
-0
_header_bar.html
apps/templates/_header_bar.html
+2
-2
auth.py
apps/users/api/auth.py
+0
-195
api_urls.py
apps/users/urls/api_urls.py
+0
-4
views_urls.py
apps/users/urls/views_urls.py
+1
-3
utils.py
apps/users/utils.py
+4
-4
login.py
apps/users/views/login.py
+3
-3
user.py
apps/users/views/user.py
+1
-1
No files found.
apps/authentication/api/__init__.py
0 → 100644
View file @
6700dc96
# -*- coding: utf-8 -*-
#
from
.auth
import
*
apps/authentication/api/auth.py
0 → 100644
View file @
6700dc96
# -*- coding: utf-8 -*-
#
import
uuid
from
django.core.cache
import
cache
from
django.urls
import
reverse
from
django.shortcuts
import
get_object_or_404
from
django.utils.translation
import
ugettext
as
_
from
rest_framework.permissions
import
AllowAny
from
rest_framework.response
import
Response
from
rest_framework.views
import
APIView
from
common.utils
import
get_logger
,
get_request_ip
from
common.permissions
import
IsOrgAdminOrAppUser
from
orgs.mixins
import
RootOrgViewMixin
from
authentication.signals
import
post_auth_success
,
post_auth_failed
from
users.serializers
import
UserSerializer
from
users.models
import
User
,
LoginLog
from
users.utils
import
(
check_user_valid
,
check_otp_code
,
increase_login_failed_count
,
is_block_login
,
clean_failed_count
)
from
users.hands
import
Asset
,
SystemUser
logger
=
get_logger
(
__name__
)
class
UserAuthApi
(
RootOrgViewMixin
,
APIView
):
permission_classes
=
(
AllowAny
,)
serializer_class
=
UserSerializer
def
post
(
self
,
request
):
# limit login
username
=
request
.
data
.
get
(
'username'
)
ip
=
request
.
data
.
get
(
'remote_addr'
,
None
)
ip
=
ip
or
get_request_ip
(
request
)
if
is_block_login
(
username
,
ip
):
msg
=
_
(
"Log in frequently and try again later"
)
logger
.
warn
(
msg
+
': '
+
username
+
':'
+
ip
)
return
Response
({
'msg'
:
msg
},
status
=
401
)
user
,
msg
=
self
.
check_user_valid
(
request
)
if
not
user
:
username
=
request
.
data
.
get
(
'username'
,
''
)
exist
=
User
.
objects
.
filter
(
username
=
username
)
.
first
()
reason
=
LoginLog
.
REASON_PASSWORD
if
exist
else
LoginLog
.
REASON_NOT_EXIST
self
.
send_auth_signal
(
success
=
False
,
username
=
username
,
reason
=
reason
)
increase_login_failed_count
(
username
,
ip
)
return
Response
({
'msg'
:
msg
},
status
=
401
)
if
user
.
password_has_expired
:
self
.
send_auth_signal
(
success
=
False
,
username
=
username
,
reason
=
LoginLog
.
REASON_PASSWORD_EXPIRED
)
msg
=
_
(
"The user {} password has expired, please update."
.
format
(
user
.
username
))
logger
.
info
(
msg
)
return
Response
({
'msg'
:
msg
},
status
=
401
)
if
not
user
.
otp_enabled
:
self
.
send_auth_signal
(
success
=
True
,
user
=
user
)
# 登陆成功,清除原来的缓存计数
clean_failed_count
(
username
,
ip
)
token
=
user
.
create_bearer_token
(
request
)
return
Response
(
{
'token'
:
token
,
'user'
:
self
.
serializer_class
(
user
)
.
data
}
)
seed
=
uuid
.
uuid4
()
.
hex
cache
.
set
(
seed
,
user
,
300
)
return
Response
(
{
'code'
:
101
,
'msg'
:
_
(
'Please carry seed value and '
'conduct MFA secondary certification'
),
'otp_url'
:
reverse
(
'api-auth:user-otp-auth'
),
'seed'
:
seed
,
'user'
:
self
.
serializer_class
(
user
)
.
data
},
status
=
300
)
@staticmethod
def
check_user_valid
(
request
):
username
=
request
.
data
.
get
(
'username'
,
''
)
password
=
request
.
data
.
get
(
'password'
,
''
)
public_key
=
request
.
data
.
get
(
'public_key'
,
''
)
user
,
msg
=
check_user_valid
(
username
=
username
,
password
=
password
,
public_key
=
public_key
)
return
user
,
msg
def
send_auth_signal
(
self
,
success
=
True
,
user
=
None
,
username
=
''
,
reason
=
''
):
if
success
:
post_auth_success
.
send
(
sender
=
self
.
__class__
,
user
=
user
,
request
=
self
.
request
)
else
:
post_auth_failed
.
send
(
sender
=
self
.
__class__
,
username
=
username
,
request
=
self
.
request
,
reason
=
reason
)
class
UserConnectionTokenApi
(
RootOrgViewMixin
,
APIView
):
permission_classes
=
(
IsOrgAdminOrAppUser
,)
def
post
(
self
,
request
):
user_id
=
request
.
data
.
get
(
'user'
,
''
)
asset_id
=
request
.
data
.
get
(
'asset'
,
''
)
system_user_id
=
request
.
data
.
get
(
'system_user'
,
''
)
token
=
str
(
uuid
.
uuid4
())
user
=
get_object_or_404
(
User
,
id
=
user_id
)
asset
=
get_object_or_404
(
Asset
,
id
=
asset_id
)
system_user
=
get_object_or_404
(
SystemUser
,
id
=
system_user_id
)
value
=
{
'user'
:
user_id
,
'username'
:
user
.
username
,
'asset'
:
asset_id
,
'hostname'
:
asset
.
hostname
,
'system_user'
:
system_user_id
,
'system_user_name'
:
system_user
.
name
}
cache
.
set
(
token
,
value
,
timeout
=
20
)
return
Response
({
"token"
:
token
},
status
=
201
)
def
get
(
self
,
request
):
token
=
request
.
query_params
.
get
(
'token'
)
user_only
=
request
.
query_params
.
get
(
'user-only'
,
None
)
value
=
cache
.
get
(
token
,
None
)
if
not
value
:
return
Response
(
''
,
status
=
404
)
if
not
user_only
:
return
Response
(
value
)
else
:
return
Response
({
'user'
:
value
[
'user'
]})
def
get_permissions
(
self
):
if
self
.
request
.
query_params
.
get
(
'user-only'
,
None
):
self
.
permission_classes
=
(
AllowAny
,)
return
super
()
.
get_permissions
()
class
UserToken
(
APIView
):
permission_classes
=
(
AllowAny
,)
def
post
(
self
,
request
):
if
not
request
.
user
.
is_authenticated
:
username
=
request
.
data
.
get
(
'username'
,
''
)
email
=
request
.
data
.
get
(
'email'
,
''
)
password
=
request
.
data
.
get
(
'password'
,
''
)
public_key
=
request
.
data
.
get
(
'public_key'
,
''
)
user
,
msg
=
check_user_valid
(
username
=
username
,
email
=
email
,
password
=
password
,
public_key
=
public_key
)
else
:
user
=
request
.
user
msg
=
None
if
user
:
token
=
user
.
create_bearer_token
(
request
)
return
Response
({
'Token'
:
token
,
'Keyword'
:
'Bearer'
},
status
=
200
)
else
:
return
Response
({
'error'
:
msg
},
status
=
406
)
class
UserOtpAuthApi
(
RootOrgViewMixin
,
APIView
):
permission_classes
=
(
AllowAny
,)
serializer_class
=
UserSerializer
def
post
(
self
,
request
):
otp_code
=
request
.
data
.
get
(
'otp_code'
,
''
)
seed
=
request
.
data
.
get
(
'seed'
,
''
)
user
=
cache
.
get
(
seed
,
None
)
if
not
user
:
return
Response
(
{
'msg'
:
_
(
'Please verify the user name and password first'
)},
status
=
401
)
if
not
check_otp_code
(
user
.
otp_secret_key
,
otp_code
):
self
.
send_auth_signal
(
success
=
False
,
username
=
user
.
username
,
reason
=
LoginLog
.
REASON_MFA
)
return
Response
({
'msg'
:
_
(
'MFA certification failed'
)},
status
=
401
)
self
.
send_auth_signal
(
success
=
True
,
user
=
user
)
token
=
user
.
create_bearer_token
(
request
)
data
=
{
'token'
:
token
,
'user'
:
self
.
serializer_class
(
user
)
.
data
}
return
Response
(
data
)
def
send_auth_signal
(
self
,
success
=
True
,
user
=
None
,
username
=
''
,
reason
=
''
):
if
success
:
post_auth_success
.
send
(
sender
=
self
.
__class__
,
user
=
user
,
request
=
self
.
request
)
else
:
post_auth_failed
.
send
(
sender
=
self
.
__class__
,
username
=
username
,
request
=
self
.
request
,
reason
=
reason
)
apps/
users
/authentication.py
→
apps/
authentication
/authentication.py
View file @
6700dc96
...
@@ -14,7 +14,7 @@ from rest_framework import authentication, exceptions
...
@@ -14,7 +14,7 @@ from rest_framework import authentication, exceptions
from
rest_framework.authentication
import
CSRFCheck
from
rest_framework.authentication
import
CSRFCheck
from
common.utils
import
get_object_or_none
,
make_signature
,
http_to_unixtime
from
common.utils
import
get_object_or_none
,
make_signature
,
http_to_unixtime
from
.models
import
User
,
AccessKey
,
PrivateToken
from
users
.models
import
User
,
AccessKey
,
PrivateToken
def
get_request_date_header
(
request
):
def
get_request_date_header
(
request
):
...
...
apps/authentication/urls/api_urls.py
View file @
6700dc96
# coding:utf-8
#
from
__future__
import
absolute_import
from
django.urls
import
path
from
..
import
api
app_name
=
'authentication'
urlpatterns
=
[
# path('token/', api.UserToken.as_view(), name='user-token'),
path
(
'auth/'
,
api
.
UserAuthApi
.
as_view
(),
name
=
'user-auth'
),
path
(
'connection-token/'
,
api
.
UserConnectionTokenApi
.
as_view
(),
name
=
'connection-token'
),
path
(
'otp/auth/'
,
api
.
UserOtpAuthApi
.
as_view
(),
name
=
'user-otp-auth'
),
]
apps/authentication/urls/view_urls.py
View file @
6700dc96
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
#
#
from
django.urls
import
path
from
django.urls
import
path
from
..
import
views
from
..
import
views
app_name
=
'authentication'
app_name
=
'authentication'
...
@@ -9,6 +10,11 @@ app_name = 'authentication'
...
@@ -9,6 +10,11 @@ app_name = 'authentication'
urlpatterns
=
[
urlpatterns
=
[
# openid
# openid
path
(
'openid/login/'
,
views
.
OpenIDLoginView
.
as_view
(),
name
=
'openid-login'
),
path
(
'openid/login/'
,
views
.
OpenIDLoginView
.
as_view
(),
name
=
'openid-login'
),
path
(
'openid/login/complete/'
,
views
.
OpenIDLoginCompleteView
.
as_view
(),
path
(
'openid/login/complete/'
,
name
=
'openid-login-complete'
),
views
.
OpenIDLoginCompleteView
.
as_view
(),
name
=
'openid-login-complete'
),
# login
path
(
'login/'
,
views
.
UserLoginView
.
as_view
(),
name
=
'login'
),
path
(
'login/otp/'
,
views
.
UserLoginOtpView
.
as_view
(),
name
=
'login-otp'
),
path
(
'logout/'
,
views
.
UserLogoutView
.
as_view
(),
name
=
'logout'
),
]
]
apps/authentication/views/__init__.py
View file @
6700dc96
...
@@ -2,3 +2,4 @@
...
@@ -2,3 +2,4 @@
#
#
from
.openid
import
*
from
.openid
import
*
from
.login
import
*
apps/authentication/views/login.py
View file @
6700dc96
# ~*~ coding: utf-8 ~*~
# ~*~ coding: utf-8 ~*~
#
from
__future__
import
unicode_literals
from
__future__
import
unicode_literals
import
os
import
os
from
django.core.cache
import
cache
from
django.core.cache
import
cache
from
django.shortcuts
import
render
from
django.utils
import
timezone
from
django.contrib.auth
import
login
as
auth_login
,
logout
as
auth_logout
from
django.contrib.auth
import
login
as
auth_login
,
logout
as
auth_logout
from
django.contrib.auth.mixins
import
LoginRequiredMixin
from
django.http
import
HttpResponse
from
django.views.generic
import
ListView
from
django.core.files.storage
import
default_storage
from
django.http
import
HttpResponseRedirect
,
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.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
...
@@ -19,23 +15,20 @@ from django.views.decorators.debug import sensitive_post_parameters
...
@@ -19,23 +15,20 @@ from django.views.decorators.debug import sensitive_post_parameters
from
django.views.generic.base
import
TemplateView
from
django.views.generic.base
import
TemplateView
from
django.views.generic.edit
import
FormView
from
django.views.generic.edit
import
FormView
from
django.conf
import
settings
from
django.conf
import
settings
from
formtools.wizard.views
import
SessionWizardView
from
common.utils
import
get_
object_or_none
,
get_
request_ip
from
common.utils
import
get_request_ip
from
authentication.signals
import
post_auth_success
,
post_auth_failed
from
authentication.signals
import
post_auth_success
,
post_auth_failed
from
users.models
import
User
,
LoginLog
from
users.utils
import
send_reset_password_mail
,
check_otp_code
,
\
redirect_user_first_login_or_index
,
get_user_or_tmp_user
,
\
set_tmp_user_to_cache
,
get_password_check_rules
,
check_password_rules
,
\
is_block_login
,
increase_login_failed_count
,
clean_failed_count
from
users
import
forms
from
users
import
forms
from
users.models
import
User
,
LoginLog
from
users.utils
import
(
check_otp_code
,
is_block_login
,
clean_failed_count
,
get_user_or_tmp_user
,
set_tmp_user_to_cache
,
increase_login_failed_count
,
redirect_user_first_login_or_index
,
)
__all__
=
[
__all__
=
[
'UserLoginView'
,
'UserLoginOtpView'
,
'UserLogoutView'
,
'UserLoginView'
,
'UserLoginOtpView'
,
'UserLogoutView'
,
'UserForgotPasswordView'
,
'UserForgotPasswordSendmailSuccessView'
,
'UserResetPasswordView'
,
'UserResetPasswordSuccessView'
,
'UserFirstLoginView'
,
'LoginLogListView'
]
]
...
@@ -122,7 +115,7 @@ class UserLoginView(FormView):
...
@@ -122,7 +115,7 @@ class UserLoginView(FormView):
if
user
.
otp_enabled
and
user
.
otp_secret_key
:
if
user
.
otp_enabled
and
user
.
otp_secret_key
:
# 1,2,mfa_setting & T
# 1,2,mfa_setting & T
return
reverse
(
'
users
:login-otp'
)
return
reverse
(
'
authentication
:login-otp'
)
elif
user
.
otp_enabled
and
not
user
.
otp_secret_key
:
elif
user
.
otp_enabled
and
not
user
.
otp_secret_key
:
# 1,2,mfa_setting & F
# 1,2,mfa_setting & F
return
reverse
(
'users:user-otp-enable-authentication'
)
return
reverse
(
'users:user-otp-enable-authentication'
)
...
@@ -169,7 +162,9 @@ class UserLoginOtpView(FormView):
...
@@ -169,7 +162,9 @@ class UserLoginOtpView(FormView):
success
=
False
,
username
=
user
.
username
,
success
=
False
,
username
=
user
.
username
,
reason
=
LoginLog
.
REASON_MFA
reason
=
LoginLog
.
REASON_MFA
)
)
form
.
add_error
(
'otp_code'
,
_
(
'MFA code invalid, or ntp sync server time'
))
form
.
add_error
(
'otp_code'
,
_
(
'MFA code invalid, or ntp sync server time'
)
)
return
super
()
.
form_invalid
(
form
)
return
super
()
.
form_invalid
(
form
)
def
get_success_url
(
self
):
def
get_success_url
(
self
):
...
@@ -202,7 +197,7 @@ class UserLogoutView(TemplateView):
...
@@ -202,7 +197,7 @@ class UserLogoutView(TemplateView):
'title'
:
_
(
'Logout success'
),
'title'
:
_
(
'Logout success'
),
'messages'
:
_
(
'Logout success, return login page'
),
'messages'
:
_
(
'Logout success, return login page'
),
'interval'
:
1
,
'interval'
:
1
,
'redirect_url'
:
reverse
(
'
users
:login'
),
'redirect_url'
:
reverse
(
'
authentication
:login'
),
'auto_redirect'
:
True
,
'auto_redirect'
:
True
,
}
}
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
...
...
apps/jumpserver/settings.py
View file @
6700dc96
...
@@ -135,7 +135,7 @@ TEMPLATES = [
...
@@ -135,7 +135,7 @@ TEMPLATES = [
# WSGI_APPLICATION = 'jumpserver.wsgi.applications'
# WSGI_APPLICATION = 'jumpserver.wsgi.applications'
LOGIN_REDIRECT_URL
=
reverse_lazy
(
'index'
)
LOGIN_REDIRECT_URL
=
reverse_lazy
(
'index'
)
LOGIN_URL
=
reverse_lazy
(
'
users
:login'
)
LOGIN_URL
=
reverse_lazy
(
'
authentication
:login'
)
SESSION_COOKIE_DOMAIN
=
CONFIG
.
SESSION_COOKIE_DOMAIN
SESSION_COOKIE_DOMAIN
=
CONFIG
.
SESSION_COOKIE_DOMAIN
CSRF_COOKIE_DOMAIN
=
CONFIG
.
CSRF_COOKIE_DOMAIN
CSRF_COOKIE_DOMAIN
=
CONFIG
.
CSRF_COOKIE_DOMAIN
...
@@ -343,10 +343,10 @@ REST_FRAMEWORK = {
...
@@ -343,10 +343,10 @@ REST_FRAMEWORK = {
),
),
'DEFAULT_AUTHENTICATION_CLASSES'
:
(
'DEFAULT_AUTHENTICATION_CLASSES'
:
(
# 'rest_framework.authentication.BasicAuthentication',
# 'rest_framework.authentication.BasicAuthentication',
'
users
.authentication.AccessKeyAuthentication'
,
'
authentication
.authentication.AccessKeyAuthentication'
,
'
users
.authentication.AccessTokenAuthentication'
,
'
authentication
.authentication.AccessTokenAuthentication'
,
'
users
.authentication.PrivateTokenAuthentication'
,
'
authentication
.authentication.PrivateTokenAuthentication'
,
'
users
.authentication.SessionAuthentication'
,
'
authentication
.authentication.SessionAuthentication'
,
),
),
'DEFAULT_FILTER_BACKENDS'
:
(
'DEFAULT_FILTER_BACKENDS'
:
(
'django_filters.rest_framework.DjangoFilterBackend'
,
'django_filters.rest_framework.DjangoFilterBackend'
,
...
...
apps/jumpserver/urls.py
View file @
6700dc96
...
@@ -21,6 +21,7 @@ api_v1_patterns = [
...
@@ -21,6 +21,7 @@ api_v1_patterns = [
path
(
'audits/v1/'
,
include
(
'audits.urls.api_urls'
,
namespace
=
'api-audits'
)),
path
(
'audits/v1/'
,
include
(
'audits.urls.api_urls'
,
namespace
=
'api-audits'
)),
path
(
'orgs/v1/'
,
include
(
'orgs.urls.api_urls'
,
namespace
=
'api-orgs'
)),
path
(
'orgs/v1/'
,
include
(
'orgs.urls.api_urls'
,
namespace
=
'api-orgs'
)),
path
(
'settings/v1/'
,
include
(
'settings.urls.api_urls'
,
namespace
=
'api-settings'
)),
path
(
'settings/v1/'
,
include
(
'settings.urls.api_urls'
,
namespace
=
'api-settings'
)),
path
(
'authentication/v1/'
,
include
(
'authentication.urls.api_urls'
,
namespace
=
'api-auth'
)),
]))
]))
]
]
...
...
apps/templates/_header_bar.html
View file @
6700dc96
...
@@ -94,10 +94,10 @@
...
@@ -94,10 +94,10 @@
<li><a
id=
"switch_user"
><i
class=
"fa fa-exchange"
></i><span>
{% trans 'User page' %}
</span></a></li>
<li><a
id=
"switch_user"
><i
class=
"fa fa-exchange"
></i><span>
{% trans 'User page' %}
</span></a></li>
{% endif %}
{% endif %}
{% endif %}
{% endif %}
<li><a
href=
"{% url '
users
:logout' %}"
><i
class=
"fa fa-sign-out"
></i>
{% trans 'Logout' %}
</a></li>
<li><a
href=
"{% url '
authentication
:logout' %}"
><i
class=
"fa fa-sign-out"
></i>
{% trans 'Logout' %}
</a></li>
</ul>
</ul>
{% else %}
{% else %}
<a
href=
"{% url '
users
:login' %}"
>
<a
href=
"{% url '
authentication
:login' %}"
>
<i
class=
"fa fa-sign-in"
></i>
{% trans 'Login' %}
<i
class=
"fa fa-sign-in"
></i>
{% trans 'Login' %}
</a>
</a>
{% endif %}
{% endif %}
...
...
apps/users/api/auth.py
View file @
6700dc96
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#
#
import
uuid
from
django.core.cache
import
cache
from
django.urls
import
reverse
from
django.shortcuts
import
get_object_or_404
from
django.utils.translation
import
ugettext
as
_
from
rest_framework.permissions
import
AllowAny
from
rest_framework.response
import
Response
from
rest_framework.views
import
APIView
from
common.utils
import
get_logger
,
get_request_ip
from
common.permissions
import
IsOrgAdminOrAppUser
from
orgs.mixins
import
RootOrgViewMixin
from
authentication.signals
import
post_auth_success
,
post_auth_failed
from
..serializers
import
UserSerializer
from
..models
import
User
,
LoginLog
from
..utils
import
check_user_valid
,
check_otp_code
,
\
increase_login_failed_count
,
is_block_login
,
\
clean_failed_count
from
..hands
import
Asset
,
SystemUser
logger
=
get_logger
(
__name__
)
class
UserAuthApi
(
RootOrgViewMixin
,
APIView
):
permission_classes
=
(
AllowAny
,)
serializer_class
=
UserSerializer
def
post
(
self
,
request
):
# limit login
username
=
request
.
data
.
get
(
'username'
)
ip
=
request
.
data
.
get
(
'remote_addr'
,
None
)
ip
=
ip
or
get_request_ip
(
request
)
if
is_block_login
(
username
,
ip
):
msg
=
_
(
"Log in frequently and try again later"
)
logger
.
warn
(
msg
+
': '
+
username
+
':'
+
ip
)
return
Response
({
'msg'
:
msg
},
status
=
401
)
user
,
msg
=
self
.
check_user_valid
(
request
)
if
not
user
:
username
=
request
.
data
.
get
(
'username'
,
''
)
exist
=
User
.
objects
.
filter
(
username
=
username
)
.
first
()
reason
=
LoginLog
.
REASON_PASSWORD
if
exist
else
LoginLog
.
REASON_NOT_EXIST
self
.
send_auth_signal
(
success
=
False
,
username
=
username
,
reason
=
reason
)
increase_login_failed_count
(
username
,
ip
)
return
Response
({
'msg'
:
msg
},
status
=
401
)
if
user
.
password_has_expired
:
self
.
send_auth_signal
(
success
=
False
,
username
=
username
,
reason
=
LoginLog
.
REASON_PASSWORD_EXPIRED
)
msg
=
_
(
"The user {} password has expired, please update."
.
format
(
user
.
username
))
logger
.
info
(
msg
)
return
Response
({
'msg'
:
msg
},
status
=
401
)
if
not
user
.
otp_enabled
:
self
.
send_auth_signal
(
success
=
True
,
user
=
user
)
# 登陆成功,清除原来的缓存计数
clean_failed_count
(
username
,
ip
)
token
=
user
.
create_bearer_token
(
request
)
return
Response
(
{
'token'
:
token
,
'user'
:
self
.
serializer_class
(
user
)
.
data
}
)
seed
=
uuid
.
uuid4
()
.
hex
cache
.
set
(
seed
,
user
,
300
)
return
Response
(
{
'code'
:
101
,
'msg'
:
_
(
'Please carry seed value and '
'conduct MFA secondary certification'
),
'otp_url'
:
reverse
(
'api-users:user-otp-auth'
),
'seed'
:
seed
,
'user'
:
self
.
serializer_class
(
user
)
.
data
},
status
=
300
)
@staticmethod
def
check_user_valid
(
request
):
username
=
request
.
data
.
get
(
'username'
,
''
)
password
=
request
.
data
.
get
(
'password'
,
''
)
public_key
=
request
.
data
.
get
(
'public_key'
,
''
)
user
,
msg
=
check_user_valid
(
username
=
username
,
password
=
password
,
public_key
=
public_key
)
return
user
,
msg
def
send_auth_signal
(
self
,
success
=
True
,
user
=
None
,
username
=
''
,
reason
=
''
):
if
success
:
post_auth_success
.
send
(
sender
=
self
.
__class__
,
user
=
user
,
request
=
self
.
request
)
else
:
post_auth_failed
.
send
(
sender
=
self
.
__class__
,
username
=
username
,
request
=
self
.
request
,
reason
=
reason
)
class
UserConnectionTokenApi
(
RootOrgViewMixin
,
APIView
):
permission_classes
=
(
IsOrgAdminOrAppUser
,)
def
post
(
self
,
request
):
user_id
=
request
.
data
.
get
(
'user'
,
''
)
asset_id
=
request
.
data
.
get
(
'asset'
,
''
)
system_user_id
=
request
.
data
.
get
(
'system_user'
,
''
)
token
=
str
(
uuid
.
uuid4
())
user
=
get_object_or_404
(
User
,
id
=
user_id
)
asset
=
get_object_or_404
(
Asset
,
id
=
asset_id
)
system_user
=
get_object_or_404
(
SystemUser
,
id
=
system_user_id
)
value
=
{
'user'
:
user_id
,
'username'
:
user
.
username
,
'asset'
:
asset_id
,
'hostname'
:
asset
.
hostname
,
'system_user'
:
system_user_id
,
'system_user_name'
:
system_user
.
name
}
cache
.
set
(
token
,
value
,
timeout
=
20
)
return
Response
({
"token"
:
token
},
status
=
201
)
def
get
(
self
,
request
):
token
=
request
.
query_params
.
get
(
'token'
)
user_only
=
request
.
query_params
.
get
(
'user-only'
,
None
)
value
=
cache
.
get
(
token
,
None
)
if
not
value
:
return
Response
(
''
,
status
=
404
)
if
not
user_only
:
return
Response
(
value
)
else
:
return
Response
({
'user'
:
value
[
'user'
]})
def
get_permissions
(
self
):
if
self
.
request
.
query_params
.
get
(
'user-only'
,
None
):
self
.
permission_classes
=
(
AllowAny
,)
return
super
()
.
get_permissions
()
class
UserToken
(
APIView
):
permission_classes
=
(
AllowAny
,)
def
post
(
self
,
request
):
if
not
request
.
user
.
is_authenticated
:
username
=
request
.
data
.
get
(
'username'
,
''
)
email
=
request
.
data
.
get
(
'email'
,
''
)
password
=
request
.
data
.
get
(
'password'
,
''
)
public_key
=
request
.
data
.
get
(
'public_key'
,
''
)
user
,
msg
=
check_user_valid
(
username
=
username
,
email
=
email
,
password
=
password
,
public_key
=
public_key
)
else
:
user
=
request
.
user
msg
=
None
if
user
:
token
=
user
.
create_bearer_token
(
request
)
return
Response
({
'Token'
:
token
,
'Keyword'
:
'Bearer'
},
status
=
200
)
else
:
return
Response
({
'error'
:
msg
},
status
=
406
)
class
UserOtpAuthApi
(
RootOrgViewMixin
,
APIView
):
permission_classes
=
(
AllowAny
,)
serializer_class
=
UserSerializer
def
post
(
self
,
request
):
otp_code
=
request
.
data
.
get
(
'otp_code'
,
''
)
seed
=
request
.
data
.
get
(
'seed'
,
''
)
user
=
cache
.
get
(
seed
,
None
)
if
not
user
:
return
Response
(
{
'msg'
:
_
(
'Please verify the user name and password first'
)},
status
=
401
)
if
not
check_otp_code
(
user
.
otp_secret_key
,
otp_code
):
self
.
send_auth_signal
(
success
=
False
,
username
=
user
.
username
,
reason
=
LoginLog
.
REASON_MFA
)
return
Response
({
'msg'
:
_
(
'MFA certification failed'
)},
status
=
401
)
self
.
send_auth_signal
(
success
=
True
,
user
=
user
)
token
=
user
.
create_bearer_token
(
request
)
data
=
{
'token'
:
token
,
'user'
:
self
.
serializer_class
(
user
)
.
data
}
return
Response
(
data
)
def
send_auth_signal
(
self
,
success
=
True
,
user
=
None
,
username
=
''
,
reason
=
''
):
if
success
:
post_auth_success
.
send
(
sender
=
self
.
__class__
,
user
=
user
,
request
=
self
.
request
)
else
:
post_auth_failed
.
send
(
sender
=
self
.
__class__
,
username
=
username
,
request
=
self
.
request
,
reason
=
reason
)
apps/users/urls/api_urls.py
View file @
6700dc96
...
@@ -15,11 +15,7 @@ router.register(r'groups', api.UserGroupViewSet, 'user-group')
...
@@ -15,11 +15,7 @@ router.register(r'groups', api.UserGroupViewSet, 'user-group')
urlpatterns
=
[
urlpatterns
=
[
# path('token/', api.UserToken.as_view(), name='user-token'),
path
(
'connection-token/'
,
api
.
UserConnectionTokenApi
.
as_view
(),
name
=
'connection-token'
),
path
(
'profile/'
,
api
.
UserProfileApi
.
as_view
(),
name
=
'user-profile'
),
path
(
'profile/'
,
api
.
UserProfileApi
.
as_view
(),
name
=
'user-profile'
),
path
(
'auth/'
,
api
.
UserAuthApi
.
as_view
(),
name
=
'user-auth'
),
path
(
'otp/auth/'
,
api
.
UserOtpAuthApi
.
as_view
(),
name
=
'user-otp-auth'
),
path
(
'otp/reset/'
,
api
.
UserResetOTPApi
.
as_view
(),
name
=
'my-otp-reset'
),
path
(
'otp/reset/'
,
api
.
UserResetOTPApi
.
as_view
(),
name
=
'my-otp-reset'
),
path
(
'users/<uuid:pk>/otp/reset/'
,
api
.
UserResetOTPApi
.
as_view
(),
name
=
'user-reset-otp'
),
path
(
'users/<uuid:pk>/otp/reset/'
,
api
.
UserResetOTPApi
.
as_view
(),
name
=
'user-reset-otp'
),
path
(
'users/<uuid:pk>/password/'
,
api
.
UserChangePasswordApi
.
as_view
(),
name
=
'change-user-password'
),
path
(
'users/<uuid:pk>/password/'
,
api
.
UserChangePasswordApi
.
as_view
(),
name
=
'change-user-password'
),
...
...
apps/users/urls/views_urls.py
View file @
6700dc96
...
@@ -9,8 +9,6 @@ app_name = 'users'
...
@@ -9,8 +9,6 @@ app_name = 'users'
urlpatterns
=
[
urlpatterns
=
[
# Login view
# Login view
path
(
'login/'
,
views
.
UserLoginView
.
as_view
(),
name
=
'login'
),
path
(
'login/'
,
views
.
UserLoginView
.
as_view
(),
name
=
'login'
),
path
(
'logout/'
,
views
.
UserLogoutView
.
as_view
(),
name
=
'logout'
),
path
(
'login/otp/'
,
views
.
UserLoginOtpView
.
as_view
(),
name
=
'login-otp'
),
path
(
'password/forgot/'
,
views
.
UserForgotPasswordView
.
as_view
(),
name
=
'forgot-password'
),
path
(
'password/forgot/'
,
views
.
UserForgotPasswordView
.
as_view
(),
name
=
'forgot-password'
),
path
(
'password/forgot/sendmail-success/'
,
views
.
UserForgotPasswordSendmailSuccessView
.
as_view
(),
name
=
'forgot-password-sendmail-success'
),
path
(
'password/forgot/sendmail-success/'
,
views
.
UserForgotPasswordSendmailSuccessView
.
as_view
(),
name
=
'forgot-password-sendmail-success'
),
path
(
'password/reset/'
,
views
.
UserResetPasswordView
.
as_view
(),
name
=
'reset-password'
),
path
(
'password/reset/'
,
views
.
UserResetPasswordView
.
as_view
(),
name
=
'reset-password'
),
...
@@ -50,5 +48,5 @@ urlpatterns = [
...
@@ -50,5 +48,5 @@ urlpatterns = [
# Login log
# Login log
# Abandon
# Abandon
path
(
'login-log/'
,
views
.
LoginLogListView
.
as_view
(),
name
=
'login-log-list'
),
#
path('login-log/', views.LoginLogListView.as_view(), name='login-log-list'),
]
]
apps/users/utils.py
View file @
6700dc96
...
@@ -62,7 +62,7 @@ def send_user_created_mail(user):
...
@@ -62,7 +62,7 @@ def send_user_created_mail(user):
'rest_password_token'
:
user
.
generate_reset_token
(),
'rest_password_token'
:
user
.
generate_reset_token
(),
'forget_password_url'
:
reverse
(
'users:forgot-password'
,
external
=
True
),
'forget_password_url'
:
reverse
(
'users:forgot-password'
,
external
=
True
),
'email'
:
user
.
email
,
'email'
:
user
.
email
,
'login_url'
:
reverse
(
'
users
:login'
,
external
=
True
),
'login_url'
:
reverse
(
'
authentication
:login'
,
external
=
True
),
}
}
if
settings
.
DEBUG
:
if
settings
.
DEBUG
:
try
:
try
:
...
@@ -98,7 +98,7 @@ def send_reset_password_mail(user):
...
@@ -98,7 +98,7 @@ def send_reset_password_mail(user):
'rest_password_token'
:
user
.
generate_reset_token
(),
'rest_password_token'
:
user
.
generate_reset_token
(),
'forget_password_url'
:
reverse
(
'users:forgot-password'
,
external
=
True
),
'forget_password_url'
:
reverse
(
'users:forgot-password'
,
external
=
True
),
'email'
:
user
.
email
,
'email'
:
user
.
email
,
'login_url'
:
reverse
(
'
users
:login'
,
external
=
True
),
'login_url'
:
reverse
(
'
authentication
:login'
,
external
=
True
),
}
}
if
settings
.
DEBUG
:
if
settings
.
DEBUG
:
logger
.
debug
(
message
)
logger
.
debug
(
message
)
...
@@ -136,7 +136,7 @@ def send_password_expiration_reminder_mail(user):
...
@@ -136,7 +136,7 @@ def send_password_expiration_reminder_mail(user):
'update_password_url'
:
reverse
(
'users:user-password-update'
,
external
=
True
),
'update_password_url'
:
reverse
(
'users:user-password-update'
,
external
=
True
),
'forget_password_url'
:
reverse
(
'users:forgot-password'
,
external
=
True
),
'forget_password_url'
:
reverse
(
'users:forgot-password'
,
external
=
True
),
'email'
:
user
.
email
,
'email'
:
user
.
email
,
'login_url'
:
reverse
(
'
users
:login'
,
external
=
True
),
'login_url'
:
reverse
(
'
authentication
:login'
,
external
=
True
),
}
}
if
settings
.
DEBUG
:
if
settings
.
DEBUG
:
logger
.
debug
(
message
)
logger
.
debug
(
message
)
...
@@ -158,7 +158,7 @@ def send_reset_ssh_key_mail(user):
...
@@ -158,7 +158,7 @@ def send_reset_ssh_key_mail(user):
</br>
</br>
"""
)
%
{
"""
)
%
{
'name'
:
user
.
name
,
'name'
:
user
.
name
,
'login_url'
:
reverse
(
'
users
:login'
,
external
=
True
),
'login_url'
:
reverse
(
'
authentication
:login'
,
external
=
True
),
}
}
if
settings
.
DEBUG
:
if
settings
.
DEBUG
:
logger
.
debug
(
message
)
logger
.
debug
(
message
)
...
...
apps/users/views/login.py
View file @
6700dc96
...
@@ -24,7 +24,7 @@ from .. import forms
...
@@ -24,7 +24,7 @@ from .. import forms
__all__
=
[
__all__
=
[
'UserLoginView'
,
'UserForgotPasswordSendmailSuccessView'
,
'UserLoginView'
,
'UserForgotPasswordSendmailSuccessView'
,
'UserResetPasswordSuccessView'
,
'UserResetPasswordSuccessView'
,
'UserResetPasswordSuccessView'
,
'UserResetPasswordSuccessView'
,
'UserResetPasswordView'
,
'UserForgotPasswordView'
,
'UserResetPasswordView'
,
'UserForgotPasswordView'
,
'UserFirstLoginView'
,
]
]
...
@@ -58,7 +58,7 @@ class UserForgotPasswordSendmailSuccessView(TemplateView):
...
@@ -58,7 +58,7 @@ class UserForgotPasswordSendmailSuccessView(TemplateView):
'title'
:
_
(
'Send reset password message'
),
'title'
:
_
(
'Send reset password message'
),
'messages'
:
_
(
'Send reset password mail success, '
'messages'
:
_
(
'Send reset password mail success, '
'login your mail box and follow it '
),
'login your mail box and follow it '
),
'redirect_url'
:
reverse
(
'
users
:login'
),
'redirect_url'
:
reverse
(
'
authentication
:login'
),
}
}
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
...
@@ -71,7 +71,7 @@ class UserResetPasswordSuccessView(TemplateView):
...
@@ -71,7 +71,7 @@ class UserResetPasswordSuccessView(TemplateView):
context
=
{
context
=
{
'title'
:
_
(
'Reset password success'
),
'title'
:
_
(
'Reset password success'
),
'messages'
:
_
(
'Reset password success, return to login page'
),
'messages'
:
_
(
'Reset password success, return to login page'
),
'redirect_url'
:
reverse
(
'
users
:login'
),
'redirect_url'
:
reverse
(
'
authentication
:login'
),
'auto_redirect'
:
True
,
'auto_redirect'
:
True
,
}
}
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
...
...
apps/users/views/user.py
View file @
6700dc96
...
@@ -574,7 +574,7 @@ class UserOtpSettingsSuccessView(TemplateView):
...
@@ -574,7 +574,7 @@ class UserOtpSettingsSuccessView(TemplateView):
'title'
:
title
,
'title'
:
title
,
'messages'
:
describe
,
'messages'
:
describe
,
'interval'
:
1
,
'interval'
:
1
,
'redirect_url'
:
reverse
(
'
users
:login'
),
'redirect_url'
:
reverse
(
'
authentication
:login'
),
'auto_redirect'
:
True
,
'auto_redirect'
:
True
,
}
}
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment