美文网首页
Web请求中的身份验证

Web请求中的身份验证

作者: 大爷的二舅 | 来源:发表于2018-02-22 16:05 被阅读188次

    Django使用会话和中间件将认证系统挂接到请求对象。 这些提供了代表当前用户的每个请求的request.user属性。 如果当前用户尚未登录,则此属性将设置为AnonymousUser的一个实例,否则它将是User的一个实例。 您可以使用is_authenticated()来区分它们,如下所示:

    if request.user.is_authenticated():
        # Do something for authenticated users.
    else:
        # Do something for anonymous users.
    
    如何登录用户

    要从视图登录用户,请使用login()。 它需要一个HttpRequest对象和一个User对象。 login()使用Django的会话框架将用户的ID保存在会话中。 请注意,匿名会话期间的任何数据集都将在用户登录后保留在会话中。此示例显示如何使用authenticate()和login():

    from django.contrib.auth import authenticate, login
    
    def my_view(request):
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user is not None:
            if user.is_active:
                login(request, user)
                # Redirect to a success page.
            else:
                # Return a 'disabled account' error message
        else:
            # Return an 'invalid login' error message.
    

    首先调用authenticate()首先,当您手动登录用户时,必须在调用login()之前调用authenticate()。 authenticate()在用户身上设置一个属性,指出哪个认证后端成功认证了该用户,并且此信息在登录过程中稍后需要。 如果您尝试直接登录从数据库检索到的用户对象,则会引发错误。

    如何登录用户

    要注销通过login()登录的用户,请在您的视图中使用logout()。 它需要一个HttpRequest对象并且没有返回值。 例:

    from django.contrib.auth import logout
    
    def logout_view(request):
        logout(request)
        # Redirect to a success page.
    

    请注意,如果用户未登录,logout()不会引发任何错误。当您调用logout()时,当前请求的会话数据将被彻底清除。 所有现有数据都将被删除。 这是为了防止其他人使用同一个Web浏览器登录并访问先前用户的会话数据。

    如果你想把任何东西放到注销后立即可用的会话中,那么在调用logout()之后执行该操作。

    限制对登录用户的访问
    原始的方式

    限制访问页面的简单原始方法是检查request.user.is_authenticated()并重定向到登录页面:

    from django.shortcuts import redirect
    
    def my_view(request):
        if not request.user.is_authenticated():
            return redirect('/login/?next=%s' % request.path)
        # ...
    

    ...或显示错误消息:

    from django.shortcuts import render
    
    def my_view(request):
        if not request.user.is_authenticated():
            return render(request, 'books/login_error.html')
        # ...
    
    login_required装饰器

    作为一个捷径,你可以使用方便的login_required()装饰器:

    from django.contrib.auth.decorators import login_required
    
    @login_required
    def my_view(request):
        ...
    

    login_required()执行以下操作:

    • 如果用户未登录,则重定向到LOGIN_URL,并在查询字符串中传递当前绝对路径。 例如:/ accounts / login /?next = / reviews / 3 /。
    • 如果用户登录,则正常执行视图。 视图代码可以假定用户已登录。

    默认情况下,用户在成功验证后应该重定向到的路径存储在名为“next”的查询字符串参数中。 如果您希望为此参数使用不同的名称,login_required()将采用可选的redirect_field_name参数:

    from django.contrib.auth.decorators import login_required
    
    @login_required(redirect_field_name='my_redirect_field')
    def my_view(request):
        ...
    

    请注意,如果您为redirect_field_name提供值,则很可能还需要自定义您的登录模板,因为存储重定向路径的模板上下文变量将使用redirect_field_name的值作为其键值而不是“next”(缺省值)。 login_required()也采用可选的login_url参数。 例:

    from django.contrib.auth.decorators import login_required
    
    @login_required(login_url='/accounts/login/')
    def my_view(request):
       ...
    

    请注意,如果您未指定login_url参数,则需要确保LOGIN_URL和您的登录视图正确关联。 例如,使用默认值,将以下行添加到您的URLconf中:

    from django.contrib.auth import views as auth_views
    
    url(r'^accounts/login/$', auth_views.login),
    

    LOGIN_URL还接受视图函数名称和指定的URL模式。 这使您可以在URLconf中自由重新映射登录视图,而无需更新设置。

    注意:login_required装饰器不会检查用户的is_active标志。

    限制对通过测试的登录用户的访问

    要根据某些权限或某些其他测试来限制访问权限,您的操作基本上与上一节中所描述的相同。 简单的方法是直接在视图中的request.user上运行测试。 例如,此视图会检查以确保用户在所需的域中有电子邮件:

    def my_view(request):
        if not request.user.email.endswith('@example.com'):
            return HttpResponse("You can't leave a review for this book.")
        # ...
    

    作为一个快捷方式,你可以使用方便的user_passes_test修饰器:

    from django.contrib.auth.decorators import user_passes_test
    
    def email_check(user):
        return user.email.endswith('@example.com')
    
    @user_passes_test(email_check)
    def my_view(request):
        ...
    

    user_passes_test()需要一个必需的参数:一个可调用的用户对象,如果允许用户查看页面,则返回True。 请注意,user_passes_test()不会自动检查用户是否为匿名用户。 user_passes_test()接受两个可选参数:

    1. login_url。 让您指定未通过测试的用户将被重定向到的URL。 它可能是一个登录页面,如果你没有指定登录页面,则默认为LOGIN_URL。

    2. redirect_field_name。 与login_required()相同。 将其设置为None会将其从URL中删除,如果您将未通过测试的用户重定向到没有“下一页”的非登录页面,则可能需要执行此操作。

    例如:

    @user_passes_test(email_check, login_url='/login/')
    def my_view(request):
        ...
    
    permission_required装饰器

    检查用户是否具有特定权限是相对常见的任务。 出于这个原因,Django为这种情况提供了一个快捷方式 - permission_required()装饰器:

    from django.contrib.auth.decorators import permission_required
    
    @permission_required('reviews.can_vote')
    def my_view(request):
        ...
    

    就像has_perm()方法一样,权限名称的形式为“<app label>.<permission codename>”
    (即reviews.can_vote在审查申请中对模型的许可)。 装饰器也可以获取权限列表。 请注意,permission_required()也采用可选的login_url参数。 例:

    from django.contrib.auth.decorators import permission_required
    
    @permission_required('reviews.can_vote', login_url='/loginpage/')
    def my_view(request):
        ...
    

    和login_required()装饰器一样,login_url默认为LOGIN_URL。 如果给出raise_exception参数,装饰器将引发PermissionDenied,提示403(HTTP禁止)视图,而不是重定向到登录页面。

    会话无效,密码更改

    如果您的AUTH_USER_MODEL从AbstractBaseUser继承,或者实现它自己的get_session_auth_hash()
    方法,认证会话将包含此函数返回的散列。 在AbstractBaseUser的情况下,这是密码字段的哈希消息验证码(HMAC)。

    如果启用了SessionAuthenticationMiddleware,Django会验证与每个请求一起发送的哈希与服务器端计算出的哈希相匹配。 这允许用户通过更改其密码来注销其所有会话。

    Django包含的默认密码更改视图,django.contrib.auth.views.password_change()和django.contrib.auth管理中的user_change_password视图,使用新密码哈希更新会话,以便用户更改自己的密码 不会注销。 如果您有自定义密码更改视图并希望有类似的行为,请使用此功能:

    django.contrib.auth.decorators.update_session_auth_hash (request, user)
    

    此函数接受当前请求和从中派生新会话哈希的更新用户对象,并适当地更新会话哈希。 用法示例:

    from django.contrib.auth import update_session_auth_hash
    
    def password_change(request):
        if request.method == 'POST':
            form = PasswordChangeForm(user=request.user, data=request.POST)
            if form.is_valid():
                form.save()
                update_session_auth_hash(request, form.user)
        else:
            ...
    

    由于get_session_auth_hash()基于SECRET_KEY,因此更新站点以使用新秘密将使所有现有会话无效。

    相关文章

      网友评论

          本文标题:Web请求中的身份验证

          本文链接:https://www.haomeiwen.com/subject/fgestftx.html