标签: django-authentication

Django - 测试 - @login_required装饰器的问题

问题

更新:事实证明,这个问题与@login_required装饰者没什么关系!

当我尝试测试装饰的视图时,我会遇到挑剔的行为@login_required.

我有一个测试实际上可以进入装饰的视图@login_required(密码更改视图).但是,不同的测试总是被重定向到登录.无论我尝试重写它的哪种方式,它都不会让我的测试用户通过,即使我正在记录用户并user.is_authenticated()事先断言.

以下是有问题的相关测试片段:

# Log user in
self.client.login(username=user.username, password=user.password)
self.assertTrue(user.is_authenticated())

# Go to account_edit view
url = reverse('account_edit')
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'users/account_edit_form.html')
Run Code Online (Sandbox Code Playgroud)

这不可避免地会重定向到登录视图,就好像用户没有登录一样.

我可以确认这种行为没有反映在应用程序的"正常"功能中; 当我实际运行服务器然后导航到此视图时,装饰器的工作方式完全正常(即,它允许在登录时访问,并重定向到登录视图).

使用Django 1.3.1.我正在使用来自django-nose的testrunner,但我可以确认无论我使用哪个testrunner都会发生这个问题.

此外,我发现了之前的几个问题,但建议的解决方案要么特别适用于旧版本的Django,要么在这种情况下没有帮助(例如,请参见此处).

解决方案(结合两个好的答案)

我收到了两个非常好的答案,这两个问题突出了我发布的片段中的重要疏忽.这个问题与@login_required行为无关,而且与(a)用户签名错误和(b)检查用户身份验证错误有关.

我很难选择接受哪个答案,但经过一番思考后,我决定接受KonradHałas的答案,因为它确定了我的关键疏忽,这是意外行为的根源.

尽管如此,如果我没有使用错误的测试线,我会更早地想出来self.assertTrue(user.is_authenticated()).因此,要强调解决方案实际上是两个部分,以下是修复有问题代码的两个步骤:

# Log user in *NOTE: Password needs to be raw (from Konrad's answer)
self.client.login(username=user.username, password="pass")
self.assertTrue(user.is_authenticated()) # <-- still not correct
Run Code Online (Sandbox Code Playgroud)

断言行仍然有问题,因为有效用户总是满足user.is_authenticated().有关此问题的解释,请参阅Alasdair的信息.因此修复此代码的第二步是:

# Log user in …
Run Code Online (Sandbox Code Playgroud)

python testing django unit-testing django-authentication

8
推荐指数
1
解决办法
2504
查看次数

是否可以在不修改Form类的情况下使用django-crispy-form FormHelper

为了保持一致性,我想在登录表单中使用crispy.我正在使用'django.contrib.auth.views.login',我只是编写模板.

问题是{% crispy form %}不输出提交按钮或"下一步"隐藏字段.

有没有办法FormHelperforms.py(在contrib.auth中创建,所以我需要尝试扩展AuthenticationForm或类似的东西)创建然后在模板中使用它而不修改views.py(也在contrib.auth中)

如果它需要任何ninjitsu扩展类等.我将使用纯HTML,但如果有一个简单的方法FormHelper在模板级别包含'外部' 我会后悔没有问

django django-templates django-forms django-authentication django-crispy-forms

8
推荐指数
1
解决办法
1894
查看次数

使用Requests和Django从脚本登录网页

我在Django中编写了一个Web应用程序.我需要将一些数据发布到python脚本的表单中.禁用登录时,帖子(r2)可正常工作.我有正确的登录请求(r1),但它现在给我一个404错误的表单帖子(r2).登录似乎没有转移到第二个请求.csrftoken和sessionid被硬编码用于测试,因为它没有识别它们.相关代码(删除了网址):

url_login='../pecasRunLog/accounts/login/'
url_add_run='../pecasRunLog/model/'+region+'/add_run/'

client = requests.session()
client.get(url_login)
csrftoken = client.cookies['csrftoken']
login_data = {'username':user,'password':password, 'csrfmiddlewaretoken':csrftoken, 'next': '/pecasRunLog/'}
r1=client.post(url_login,data=login_data)

payload={'model_region':region_id,'scendir':scendir, 'mapit_scenario': schema, 'run_name':schema+timestamp, 'run_computer_name':os.environ['COMPUTERNAME'], 'run_computer_ip':get_lan_ip(), 'declared_user':declared_user, 'logged_in_user':getpass.getuser(), 'sd_schema':schema, 'sd_database':database, 'sd_host':get_lan_ip(), 'sd_port':pgport,'mapit_schema':schema, 'mapit_database':database, 'mapit_host':get_lan_ip(), 'mapit_port':pgport,'start_date':start_date, 'start_time':start_time, 'end_date':end_date, 'end_time':end_time,'logged_manually':3, 'csrfmiddlewaretoken':csrftoken, 'sessionid':'jtvv50cs3iyo9bjthbr2diujfmrrlsnf'}
r2=requests.post(url_add_run,payload)
Run Code Online (Sandbox Code Playgroud)

python django django-authentication python-requests

8
推荐指数
2
解决办法
4915
查看次数

django用户模型中有多个USERNAME_FIELD

我的自定义用户模型:

class MyUser(AbstractBaseUser):
    username = models.CharField(unique=True,max_length=30)
    email = models.EmailField(unique=True,max_length=75)
    is_staff = models.IntegerField(default=False)
    is_active = models.IntegerField(default=False)
    date_joined = models.DateTimeField(default=None)

    # Use default usermanager
    objects = UserManager()

    USERNAME_FIELD = 'email'
Run Code Online (Sandbox Code Playgroud)

有没有办法指定多个USERNAME_FIELD?有类似的东西['email','username'],用户可以通过电子邮件和用户名登录?

django django-authentication django-users

8
推荐指数
2
解决办法
6832
查看次数

如何从管理界面重置用户密码

在我的网站上,我想让管理员重置任何用户的密码.

使用重置,我的意思是password_reset视图的确切功能(在contrib.auth下):发送一个确认链接到该用户电子邮件.

这样做的最好方法是什么?是否已有一个app/snippet可以做到这一点?

编辑:

假设用户john是管理员.我想要的是让john通过管理界面重置任何用户的密码.例如,要重置最大密码,他只需转到最大用户,然后单击任何链接以重置其密码.

django django-admin django-authentication

7
推荐指数
1
解决办法
8028
查看次数

Django - 没有模型的登录用户

我正在尝试实现 SSO 登录,从 saml 响应中获取所有授权权限:

class SAMLServiceProviderBackend(object):

    def authenticate(self, saml_authentication=None):
        if not saml_authentication:  # Using another authentication method
            return None

        if saml_authentication.is_authenticated():
            attributes = saml_authentication.get_attributes()
            user = User(username=saml_authentication.get_nameid())
            user.first_name = attributes['givenName']
            user.last_name = attributes['sn']

        return None
Run Code Online (Sandbox Code Playgroud)

在视图中我得到了类似的东西

...
user = authenticate(saml_authentication=auth)
login(self.request, user)
...
Run Code Online (Sandbox Code Playgroud)

login由于缺少save()方法而失败。唯一的方法是继承User并重写该save方法。尝试这个,我得到了下一个错误is_authenticatedget_and_delete_messages等等

有没有一种简单的方法可以将用户对象插入到会话中,而不将用户保存到数据库中?

就像是:

request.session['user'] = authenticate(saml_authentication=auth)
Run Code Online (Sandbox Code Playgroud)

python django django-authentication

7
推荐指数
1
解决办法
2249
查看次数

如何验证用户身份

我创建了两种不同类型的用户 - 卡车和公司。这是我的用户注册页面在此输入图像描述

注册后,有关用户是卡车还是公司的数据将进入数据库。

在我的登录页面中,登录页面

只需输入电子邮件和密码。在我的自定义用户创建表单中,我添加了字段 username = email。

当我尝试使用有效凭据登录时,该页面不会根据用户类型将我重定向到特定页面。相反,我在 login.html 中为无效凭据创建的错误正在引发 - “您的电子邮件和密码不匹配。请重试。”

这是我的代码:

视图.py:

def login_view(request):
title = "Login"

if request.method == 'POST':

    form = LoginForm(data=request.POST)
    email = request.POST.get('email', '')
    password = request.POST.get('password', '')
    user = auth.authenticate(username=email, password=password)
    if form.is_valid():
        auth.login(request, user)
        user_type = form.cleaned_data['Label']
        if user.is_active & user_type == 'Truck':
            return HttpResponseRedirect('/post_load/')
        elif user_type == 'Company':
            return HttpResponseRedirect('/live_deal/')
else:
    form = LoginForm()

return render(request, 'registration/login.html', {'form' : form, 'title': title})
Run Code Online (Sandbox Code Playgroud)

网址.py:

# url(r'^login/$', views.login_view),
# url(r'^accounts/login/$', views.login_view), …
Run Code Online (Sandbox Code Playgroud)

django django-authentication django-login django-custom-user

7
推荐指数
1
解决办法
2万
查看次数

无法为 Django 的重置密码流程创建集成测试

我正在尝试为密码重置流程实施集成测试,但我被困在“ password_reset_confirm ”视图中。我已经手动测试了流程,它工作正常。不幸的是,Django 单元测试客户端似乎无法正确遵循此视图中所需的重定向。

网址配置

from django.contrib.auth import views as auth_views


url(r"^accounts/password_change/$",
    auth_views.PasswordChangeView.as_view(),
    name="password_change"),
url(r"^accounts/password_change/done/$",
    auth_views.PasswordChangeDoneView.as_view(),
    name="password_change_done"),
url(r"^accounts/password_reset/$",
    auth_views.PasswordResetView.as_view(email_template_name="app/email/accounts/password_reset_email.html",
                                         success_url=reverse_lazy("app:password_reset_done"),
                                         subject_template_name="app/email/accounts/password_reset_subject.html"),
    name="password_reset"),
url(r"^accounts/password_reset/done/$",
    auth_views.PasswordResetDoneView.as_view(),
    name="password_reset_done"),
url(r"^accounts/reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$",
    auth_views.PasswordResetConfirmView.as_view(
        success_url=reverse_lazy("app:password_reset_complete"),
        form_class=CustomSetPasswordForm),
    name="password_reset_confirm"),
url(r"^accounts/reset/complete/$",
    auth_views.PasswordResetCompleteView.as_view(),
    name="password_reset_complete"),
Run Code Online (Sandbox Code Playgroud)

测试代码

import re
from django.urls import reverse, NoReverseMatch
from django.test import TestCase, Client
from django.core import mail
from django.test.utils import override_settings
from django.contrib.auth import authenticate

VALID_USER_NAME = "username"
USER_OLD_PSW = "oldpassword"
USER_NEW_PSW = "newpassword"
PASSWORD_RESET_URL = reverse("app:password_reset")

def PASSWORD_RESET_CONFIRM_URL(uidb64, token):
    try:
        return reverse("app:password_reset_confirm", args=(uidb64, token))
    except NoReverseMatch: …
Run Code Online (Sandbox Code Playgroud)

django django-forms django-views django-contrib django-authentication

7
推荐指数
1
解决办法
1059
查看次数

对于 Django DRF 后端来说,是否有一种身份验证方法更安全?

我想使用最安全的方法将登录的用户会话存储在 cookie 中。后端是基于 Django 和 DRF 构建的,因此我在用于令牌身份验证的 simplejwt 插件或 djangos 默认 SessionAuth 之间进行选择。前端不是 SPA,但最终也会有一个移动应用程序。所以我一直倾向于令牌身份验证,将它们存储在寿命较短的 httpOnly cookie 中。但那时,我想知道我是否本质上只是以一种迂回的方式进行会话身份验证?

对于该应用程序,一个比另一个更好(就安全性而言)?

django-authentication django-sessions django-rest-framework django-rest-framework-jwt django-rest-framework-simplejwt

7
推荐指数
1
解决办法
2242
查看次数

无法为 API 设置“DEFAULT_AUTHENTICATION_CLASSES”导入“rest_framework_jwt.authentication.JSONWebTokenAuthentication”

完整错误:无法为 API 设置“DEFAULT_AUTHENTICATION_CLASSES”导入“rest_framework_jwt.authentication.JSONWebTokenAuthentication”。ImportError:无法从“django.utils.encoding”导入名称“smart_text”

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ),
}
Run Code Online (Sandbox Code Playgroud)

这是虚拟环境中的 pip freeze:

(backend) PS D:\js\backend> pip freeze                          
asgiref==3.5.1
Django==4.0.4
django-cors-headers==3.11.0
djangorestframework==3.13.1
djangorestframework-jwt==1.11.0
djangorestframework-simplejwt==5.1.0
mysqlclient==2.1.0
PyJWT==1.7.1
pytz==2022.1
sqlparse==0.4.2
tzdata==2022.1
Run Code Online (Sandbox Code Playgroud)

在错误的中间,它解决了装饰器的views.py中的一些行:

from http.client import HTTPResponse
from multiprocessing import context
from django.shortcuts import render
from django.http import HttpResponse, Http404, JsonResponse
from .models import Tweet
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import api_view, permission_classes
from rest_framework import status
Run Code Online (Sandbox Code Playgroud)

我不确定它们是否有关联

django django-views django-authentication jwt django-rest-framework

7
推荐指数
1
解决办法
1万
查看次数