关于Django的登录系统

首先需要明确的是登录的本质:登录就是服务器确认当前用户的身份,并将数据库中的记录提取匹配

默认的登录系统是用户名密码方式,这种方式很平常,也没什么特别的.这里主要说的是第三方验证登录

通常第三方验证登录的过程就是用户使用第三方的账号验证系统进行登录验证,第三方验证通过后将该用户信息的取用凭据发给我们服务器,我们服务器使用该信息中用于辨识用户身份的唯一标示来记录或提取用户信息.

一般第三方登录只要绑定之后就不需要密码了,因为第三方已经帮我们处理了用户身份认证这一步骤.

所以在我们的服务器中,处理第三方登录的重点就放在了绑定和查询用户上,绑定就是在本地user表中添加一个第三方票据信息的字段,该字段是唯一的,所以通过该字段查询到的用户就是当前登录的用户.

django在自定义认证后端这一块做的特别灵活,我们可以自定义认证方式,然后在setting文件内注册一下就可以了.

AUTHENTICATION_BACKENDS = (
    "app.file.classBACKEND"
)

django的登录提供一个方法,login 和认证方法 authenticate

from django.contrib.auth import login, authenticate

在使用login方法之前必须先执行authenticate方法,不然login方法会报错 user没有" backend "属性

看一下authenticate方法的源码:

def authenticate(**credentials):
    """
    If the given credentials are valid, return a User object.
    """
    for backend, backend_path in _get_backends(return_tuples=True):
        try:
            inspect.getcallargs(backend.authenticate, **credentials)
        except TypeError:
            # This backend doesn't accept these credentials as arguments. Try the next one.
            continue

        try:
            user = backend.authenticate(**credentials)
        except PermissionDenied:
            # This backend says to stop in our tracks - this user should not be allowed in at all.
            return None
        if user is None:
            continue
        # Annotate the user object with the path of the backend.
        user.backend = backend_path      # 这一步给user添加了一个属性
        return user

    # The credentials supplied are invalid to all backends, fire signal
    user_login_failed.send(sender=__name__,
            credentials=_clean_credentials(credentials))

这里面会调用一个方法,该方法是将配置文件中的认证后端全部扫描一遍,然后将他们放在一个列表里,再使用这列表里面所有认证后端来对数据进行认证,只要有一个认证通过,那么就认证成功.

def _get_backends(return_tuples=False):
    backends = []
    for backend_path in settings.AUTHENTICATION_BACKENDS:
        backend = load_backend(backend_path)
        backends.append((backend, backend_path) if return_tuples else backend)
    if not backends:
        raise ImproperlyConfigured(
            'No authentication backends have been defined. Does '
            'AUTHENTICATION_BACKENDS contain anything?'
        )
    return backends

authenticate方法内的关键一步 

user = backend.authenticate(**credentials)

所以我们定义的认证后端就要实现这个方法,举例我们使用微信第三方认证, 通过unionID来认证,那么代码可以如下:

# setting文件配置:比如定义的认证后端位于 firstapp/backends.py/DSFBackend , 那么配置信息如下:
AUTHENTICATION_BACKENDS = (
    "firstapp/backends.py/DSFBackend" 
)

class DSFBackend(ModelBackend): def authenticate(self, unionid=None, **kwargs): if unionid: try: user = User.objects.get(unionid=unionid, status=User.STATUS_VALID) return user except User.DoesNotExist: return None except Exception: user = User.objects.filter(unionid=unionid, status=User.STATUS_VALID).first()return user else: return None

这样之后就可以进行login方法进行登录了

def login(request, user):
    """
    Persist a user id and a backend in the request. This way a user doesn't
    have to reauthenticate on every request. Note that data set during
    the anonymous session is retained when the user logs in.
    """
    session_auth_hash = ''
    if user is None:
        user = request.user
    if hasattr(user, 'get_session_auth_hash'):
        session_auth_hash = user.get_session_auth_hash()

    if SESSION_KEY in request.session:
        if _get_user_session_key(request) != user.pk or (
                session_auth_hash and
                request.session.get(HASH_SESSION_KEY) != session_auth_hash):
            # To avoid reusing another user's session, create a new, empty
            # session if the existing session corresponds to a different
            # authenticated user.
            request.session.flush()
    else:
        request.session.cycle_key()
    request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
    request.session[BACKEND_SESSION_KEY] = user.backend    # 这一块就是很多报错的原因,如果不行authenticate方法的话,是没有backend属性的
    request.session[HASH_SESSION_KEY] = session_auth_hash
    if hasattr(request, 'user'):
        request.user = user
    rotate_token(request)
    user_logged_in.send(sender=user.__class__, request=request, user=user)

可以看到,Django框架给我们做了很多工作,真的是最脏最累的活都被它干了.

 

转载于:https://www.cnblogs.com/haiton/p/10592206.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值