简体   繁体   English

更改页面后,Django request.user变为匿名。 使用自定义用户模型

[英]Django request.user becomes anonymous after changing page. Using custom user model

I'm using a custom user model that extends AbstractBaseUser . 我正在使用扩展AbstractBaseUser的自定义用户模型。 This is the user model: 这是用户模型:

class cUser(AbstractBaseUser):
    def save(self, *args, **kwargs):
        pass
    role_id = models.IntegerField()
    user_id = models.IntegerField()
    email = models.CharField(max_length=40)
    password = models.CharField(max_length=40)
    f_name = models.CharField(max_length=40)
    l_name = models.CharField(max_length=40)
    address_id = models.IntegerField()
    phone_num = models.IntegerField()
    loan_item_count = models.IntegerField()
    id = models.IntegerField(unique = True, primary_key = True)

    def __init__(self, dictionary, *args, **kwargs):
        self.role_id = int(dictionary['role_id'])
        self.user_id = dictionary['user_id']
        self.email = dictionary['email']
        self.password = dictionary['password']
        self.f_name = dictionary['f_name']
        self.l_name = dictionary['l_name']
        self.address_id = dictionary['address_id']
        self.phone_num = dictionary['phone_num']
        self.loan_item_count = dictionary['loan_item_count']
        self.id = self.user_id

    USERNAME_FIELD = 'user_id'
    class Meta:
        managed = False

I don't want the model to affect the DB in any way. 我不希望模型以任何方式影响数据库。 I'm loading it by a simple raw SQL query from a gateway method. 我正在通过网关方法中的简单原始SQL查询来加载它。

This is how I'm handling login: 这是我处理登录的方式:

def login_request(request):
    if request.method == 'POST':
        form = LoginForm(request.POST)
        if form.is_valid():
            username = request.POST['username']
            password = request.POST['password']
            user = userGateway(username,password)
            if user is not None:
                print("=========USER==========")
                print(user.email)
                user.backend = 'django.contrib.auth.backends.ModelBackend'
                login(request,user)
                print(request.user.is_authenticated)
                if user.role_id==1:
                    return render(request, 'biblioteca/admin/landing.html')
                    # return HttpResponseRedirect('/')
                else:
                    return render(request, 'biblioteca/landing.html')
            else:
                print("=========NOT USER==========")
    else:
        if(request.user is not None and not request.user.is_anonymous):
            return render(request, 'biblioteca/admin/landing.html')
        form = LoginForm()
        return render(request, 'biblioteca/login.html', {'form': form})

As you can see, I'm setting the back-end before login to authenticate without having to pass through a password - the password check is being done when the user object is created by comparing the password passed in with the password retrieved from the DB. 如您所见,我在登录前将后端设置为无需通过密码即可进行身份验证-通过将传入的密码与从数据库检索到的密码进行比较来创建用户对象时,便完成了密码检查。

If I return a render , as seen here, the next page contains the proper request.user object. 如果返回一个render ,如此处所示,下一页将包含正确的request.user对象。 If I return a redirect, it does not. 如果返回重定向,则不会。 Additionally, if I leave that page at all, the user becomes unauthenticated and anonymous again, losing the session. 另外,如果我根本不离开该页面,则该用户将再次变得未经身份验证且匿名,从而丢失会话。

Any help as to why this happens would be much appreciated. 对于为什么发生这种情况的任何帮助将不胜感激。

When you redirect, the request is completed and a redirect code is sent to the client, who then makes a new request to the new page without the POST data for the login form. 重定向时,请求完成,并且重定向代码发送到客户端,客户端随后向新页面发出新请求,而没有登录表单的POST数据。 The user may not be getting their token. 用户可能没有得到他们的令牌。 In that case, render a page to log them in that delays for a few seconds, then redirects them to the right spot. 在这种情况下,请渲染一个页面以将其记录在延迟中几秒钟,然后将其重定向到正确的位置。

So, this was solved by turning userGateway() into a proper auth backend and implementing it like that. 因此,可以通过将userGateway()转换为适当的auth后端并像这样实现来解决此问题。

Explanation as to why: 原因说明:

The sessionID in django stores a hash of the user's PK as well as the auth backend used to log in. Whenever a new request is sent, data needed is lazy-loaded from the DB using this hash. django中的sessionID存储用户PK的哈希值以及用于登录的auth后端。每当发送新请求时,所需的数据就使用该哈希值从数据库中延迟加载。

This is why login() was properly authenticating the user on the login page, because it was pretty much forced to. 这就是为什么login()在登录页面上正确验证用户身份的原因,因为它几乎被迫进行身份验证。 As soon as another request happened, though, it would be unable to load the user's data from the DB, and would flush the sessionid. 但是,一旦发生另一个请求,它将无法从数据库中加载用户的数据,并将刷新会话ID。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM