Django 中的身份验证扩展一对一关系

authentication in django with extending one-to-one relationship

我已经制作了用户可以基于用户模型登录的身份验证系统。在用户模型中,它以一对一的关系进行扩展。当我使用用户名和密码插入登录名时,它起作用了。但是当我使用用户名、密码和 hak_akses 插入登录名时。它不能正常工作。我希望身份验证可以使用插入用户名、密码和 hak_akses。但是,我还是不知道怎么做

这是我的urls.py

urlpatterns = patterns('',
    url(r'^login/', views.login, name='login'),
    url(r'^auth/$', views.auth_view, name="auth"),

这是我的模型

class UserProfile(models.Model):
    # This line is required. Links UserProfile to a User model instance.
    user = models.OneToOneField(User)

    # The additional attributes we wish to include.
    CATEGORY_CHOICES = (
        ('admin','Admin'),
        ('user','User'),
        )
    hak_akses = models.CharField(max_length=100, choices = CATEGORY_CHOICES)

    # Override the __unicode__() method to return out something meaningful!
    def __unicode__(self):
        return self.user.username

这是我的看法

def login(request):
    c = {}
    c.update(csrf(request))
    return render_to_response('login.html', c)

def auth_view(request):
    username = request.POST.get('username', '')
    password = request.POST.get('password', '')
    akses = User.objects.select_related().all()
    hak_akses = request.POST.get('hak_akses', '')
    user = auth.authenticate(username=username, password=password, hak_akses=hak_akses)

    if user is not None:
        auth.login(request, user)
        return HttpResponseRedirect('/simofa/')
    else:
        return HttpResponseRedirect('/simofa/login')

这是我的登录模板:

<form class="form-login" method="post" action="/simofa/auth/" name="login">{% csrf_token %}
                <h2 class="form-login-heading">SISTEM MANAJEMEN OTENTIKASI FASILKOM UI</h2>
                <div class="login-wrap">
                    <input name="username" id="username" type="text" class="form-control" placeholder="User ID" autofocus>
                    <br>
                    <input name="password" id="password" type="password" class="form-control" placeholder="Password">
                <br>
                <select name="hak_akses">
                  <option name="hak_akses" value="admin">Admin</option>
                  <option name="hak_akses" value="user">User</option>
                </select>
                    <br>
                    <br>
                    <input type="submit" value="Login" class="btn btn-theme btn-block"><i class="fa fa-lock"></i>
                </div>      
              </form>       

如果您正在使用 django 的身份验证功能(即 from django.contrib.auth import authenticate),那么您应该检查身份验证功能是如何实现的。从 django 的 source code 查看这里。在第 72 行:

 ....

    try:
        user = backend.authenticate(**credentials)
    except PermissionDenied:

  ....

和backend.authenticate是这样实现的:

def authenticate(self, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD)
        try:
            user = UserModel._default_manager.get_by_natural_key(username)
            if user.check_password(password):
                return user
        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a non-existing user (#20760).
            UserModel().set_password(password) 

如你所见,它需要 2 个参数,用户名和密码,或者如果用户名是 none,那么它从 kwargs 中获取用户名。所以如果你想像 hak_akses 这样使用你自己的字段进行身份验证,你需要像这样编写你自己的身份验证后端 django test custom authentication backend.

更简单的解决方案,制作一个将 hak_akses 作为 kwargs 的函数并进行身份验证。例如:

def custom_authenticate(self, username=None, password=None, hak_akses=None ):
    user = authenticate(username=username, password=password)
    if user is not None:
        if user.is_active:
           user_profile = UserProfile.objects.get(user=user)
           if user_profile.hak_akses == hak_akses
              return user_profile
    return None

我已经解决了我的问题。在我检查用户名和密码等身份验证后。我必须创造条件来像这样检查 hak_akses 变量。

def auth_view(request):
    username = request.POST.get('username', '')
    password = request.POST.get('password', '')
    # hak_akses = request.POST.get('hak_akses', '')
    user = auth.authenticate(username=username, password=password)

    if user is not None:
        user_profile = UserProfile.objects.get(user=user)
        auth.login(request, user)
        if user_profile.hak_akses == hak_akses:
            return HttpResponseRedirect('/simofa/')
        else:
            return HttpResponseRedirect('/simofa/login')
    else:
        return HttpResponseRedirect('/simofa/login')

非常感谢@ruddra