在初始化项目时,我想从项目设置中调用登录功能一次,并在项目中的任何位置使用输出令牌。我想使用相同的令牌是否再次调用以检查令牌是否已更改。
def login(creds):
r = requests.post(base_url + '/api/admin/login', json=creds, headers=headers, verify=False)
if r.status_code == 200:
token = r.json()['token']
return token
如果我在项目设置中调用函数,则每次都会启动函数。我不想将令牌转储到文件并每次都读取。还有其他方法吗?谢谢。
答案 0 :(得分:0)
最好的方法是分离登记,身份验证和令牌使用的责任。实际上,你会在会话中存储令牌。 Django为匿名会话提供完全支持,但是如果您希望将与该用户关联的一些数据存储在本地数据库中,这可能会限制您的应用程序。
我建议在用于保存用户名的本地数据库中设置用户模型。接下来,您将创建一个身份验证功能:
import requests
def authentication(username, password):
creds = {'username': username, 'password': password}
headers = 'whatever'
r = requests.post(base_url + '/api/admin/login', json=creds, headers=headers, verify=False)
if r.status_code == 200:
token = r.json()['token']
# Create user in the local database if it does not exist yet
user, created = User.objects.get_or_create(username=username)
return token
else:
error = 'Something went wrong'
return error
接下来,您将创建登录功能。
from django.urls import reverse
from django.http import HttpResponseRedirect
from django.contrib.auth import login
from django.shortcuts import render
def login(request):
# Check if user is authenticated by call is_authenticated() and
# additionally check if token is stored in session
if request.user.is_authenticated and request.session.get('token', False):
return HttpResponseRedirect(reverse('user_page'))
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
auth_data = authenticate(username=username, password=password)
if auth_data is not None:
# Save token in session
request.session['user_token'] = auth_data
# Get user and login
# Because you created a user in local database,
# you can login that user in this step
user = User.objects.get(username=username)
login(request, user)
next = request.POST.get('next', '/') if request.POST.get('next') else '/'
return HttpResponseRedirect(next)
else:
# Implement some error handling here
return HttpResponseRedirect(reverse('login'))
else:
return render(request, 'login.html', {})
下一个合乎逻辑的步骤是以某种方式控制这些用户令牌。装饰员来救援。您创建一个检查令牌的装饰器。例如,在这个意义上的东西:
import functools
from django.contrib.auth import REDIRECT_FIELD_NAME
from urllib.parse import urlparse
from django.shortcuts import resolve_url
from django.contrib.auth.views import redirect_to_login
def token_required(func, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
@functools.wraps(func)
def decorated_function(request, *args, **kwargs):
# Check if token is saved in session
# Redirect to login page if not
if not request.session.get('token', False):
path = request.build_absolute_uri()
resolved_login_url = resolve_url(login_url or settings.LOGIN_URL)
# If the login url is the same scheme and net location then just
# use the path as the "next" url.
login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
current_scheme, current_netloc = urlparse(path)[:2]
if ((not login_scheme or login_scheme == current_scheme) and
(not login_netloc or login_netloc == current_netloc)):
path = request.get_full_path()
return redirect_to_login(
path, resolved_login_url, redirect_field_name)
return func(request, *args, **kwargs)
return decorated_function
你需要在这里实现你的逻辑。这个装饰器只检查令牌是否存储在会话中,没有别的。然后,您将在视图中使用此装饰器,如
from django.contrib.auth import logout
@token_required
@login_required
def user_logout(request):
logout(request)
return HttpResponseRedirect('/')