Loading

39.BasicAuthentication认证

BasicAuthentication认证介绍
  • BasicAuthentication使用HTTP基本的认证机制
  • 通过用户名/密码的方式验证,通常用于测试工作,尽量不要线上使用
  • 用户名和密码必须在HTTP报文头部,为 Authorization 属性提供值为 Basic amFjazpmZWl4dWVsb3ZlMTAw 的方式提供
  • 其中 Basic 字符串是键,后面的一串乱码是通过base64 库使用明文的用户名和密码计算出的密文
 
BasicAuthentication属性
# 如果认证成功BasicAuthentication下面的属性
request.user设置为Django的User类的实例
request.auth设置为None
# 未认证成功
# 响应HTTP 401 Unauthorized,并携带对应头部信息
WWW_Authenticate: Basic realm = 'api'
 
BaseicAuthentication认证类源码解析
 
#继承BaseAuthentication认证基类
#BaseAuthentication只是留了authenticate和authenticate_header两个方法,待继承类实现
class BasicAuthentication(BaseAuthentication):

    www_authenticate_realm = 'api'

        # 使用HTTP的基本authentication属性,提供正确的用户名和密码,返回一个user,否则返回None
        def authenticate(self, request):
        # 从http报头读取密文。分割字符串
        auth = get_authorization_header(request).split()
        # 如果分割出来的字符串第一部分不是basic开头,认证失败返回None
        if not auth or auth[0].lower() != b'basic':
            return None
        # 如果长度等于1 只有basic,说明没有提供用户名和密码 认证失败
        if len(auth) == 1:
            msg = _('Invalid basic header. No credentials provided.')
            raise exceptions.AuthenticationFailed(msg)
        # 如果分割出的数量 大于2,说明 basic 密文的格式不对,空格太对,认证失败
        elif len(auth) > 2:
            msg = _('Invalid basic header. Credentials string should not contain spaces.')
            raise exceptions.AuthenticationFailed(msg)

        try:
            # 获取密文部分,使用base64库进行解码,尝试两种编码方式
            try:
                auth_decoded = base64.b64decode(auth[1]).decode('utf-8')
            except UnicodeDecodeError:
                auth_decoded = base64.b64decode(auth[1]).decode('latin-1')
            auth_parts = auth_decoded.partition(':')
        # 解码失败,返回认证失败的异常
        except (TypeError, UnicodeDecodeError, binascii.Error):
            msg = _('Invalid basic header. Credentials not correctly base64 encoded.')
            raise exceptions.AuthenticationFailed(msg)
        # 解码成功,拿到明文的用户名和密码    
        userid, password = auth_parts[0], auth_parts[2]
        # 进行密码比对,返回认证结果
        return self.authenticate_credentials(userid, password, request)
    # 用户密码比对
    def authenticate_credentials(self, userid, password, request=None):
       
        credentials = {
            get_user_model().USERNAME_FIELD: userid,
            'password': password
        }
        user = authenticate(request=request, **credentials)

        if user is None:
            raise exceptions.AuthenticationFailed(_('Invalid username/password.'))

        if not user.is_active:
            raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))

        return (user, None)
    # 设置Basic realm头
    def authenticate_header(self, request):
        return 'Basic realm="%s"' % self.www_authenticate_realm
 
 
 

posted @ 2022-10-09 11:33  木子七  阅读(170)  评论(0编辑  收藏  举报