美文网首页
58.4-密码安全问题和登录接口实现

58.4-密码安全问题和登录接口实现

作者: BeautifulSoulpy | 来源:发表于2020-08-15 10:05 被阅读0次

    机遇总是有的,如果把握不住,不要怨天忧人,只因自己不够优秀;不要把时间当垃圾处理,唯有珍惜光阴,才能提升生命的质量!


    总结:

    1. 用户注册登录名重复怎么解决;
    2. 如何对密码进行加密;
    3. 如果要发一些数据发送到第三方客户端,有没有第三种解决方案jwt(防篡改);

    密码

    使用邮箱 + 密码方式登录。
    邮箱要求唯一就行了,但是,密码如何存储?

    早期,都是明文的密码存储。
    后来,使用MD5存储,但是,目前也不安全,网上有很多MD5的网站,使用反查方式找到密码。

    加盐,使用hash(password + salt)的结果存入数据库中,就算拿到数据库的密码反查,也没有用了。如果是固定加盐,还是容易被找到规律,或者从源码中泄露。随机加盐,每一次盐都变,就增加了破解的难度。

    暴力破解, 什么密码都不能保证不被暴力破解, 例如穷举。所以要使用慢hash算法, 例如b crypt, 就会让每一次计算都很慢, 都是秒级的, 这样穷举的时间就会很长,为了一个密码破解的时间在当前CPU或者GPU的计算能力下可能需要几十年以上;

    BCrypt

    BCrypt加密算法,号称目前最安全的算法之一
    哈希(Hash)是将目标文本转换成具有相同长度的、不可逆的杂凑字符串(或叫做消息摘要),而加密(Encrypt)是将目标文本转换成具有不同长度的、可逆的密文。

    pip install bcrypt
    

    哈希算法,32位,往往被设计成生成具有相同长度的文本,而加密算法生成的文本长度与明文本身的长度有关。哈希算法是不可逆的,而加密算法是可逆的。

    从耗时看出, b crypt加密、验证非常耗时, 所以如果穷举, 非常耗时。而且碰巧攻破一个密码, 由于盐不一样, 还得穷举另一个;

    salt=b'$2b$12$jwBD7mg9stvIPydF2bqoPO'
    b'$2b$12$jwBD7mg9stvIPydF2bqoPOod PwW YV vdmZb5uwWuwvlf9iHqNlKSQO'
    $是分隔符
    $2b$,加密算法
    12, 表示2^12key expansion rounds
    这是盐b'jwBD7mg9stvIPydF2bqoPO', 22个字符, Base 64
    这是密文b'odP wWYVvdmZb5uwWuwvlf9iHqNl KS QO', 31个字符, Base 64
    
    import bcrypt
    import datetime
    
    password = b'123456'
    # 每次拿到盐都不一样
    print(1, bcrypt.gensalt())
    print(2, bcrypt.gensalt())
    salt = bcrypt.gensalt()
    
    # 拿到的盐相同,计算等到的密文相同
    print('=========same salt ==========')
    x = bcrypt.hashpw(password, salt)
    print(3, x)
    x = bcrypt.hashpw(password, salt)
    print(4, x)
    
    # 每次拿到的盐不同,计算生成的密文也不一样
    print('=========different salt ==========')
    x = bcrypt.hashpw(password, bcrypt.gensalt())
    print(5, x)
    x = bcrypt.hashpw(password, bcrypt.gensalt())
    print(6, x)
    
    # 校验
    print(bcrypt.checkpw(password, x), len(x))
    print(bcrypt.checkpw(password + b' ', x), len(x))   # 错误校验方法;
    
    # 计算时长
    start = datetime.datetime.now()
    y = bcrypt.hashpw(password, bcrypt.gensalt())
    delta = (datetime.datetime.now() - start).total_seconds()
    print(10, 'duration={}'.format(delta))
    
    
    # 检验时长
    start = datetime.datetime.now()
    y = bcrypt.checkpw(password, x)
    delta = (datetime.datetime.now() - start).total_seconds()
    print(y)
    print(11, 'duration={}'.format(delta))
    start = datetime.datetime.now()
    y = bcrypt.checkpw(b'1', x)
    delta = (datetime.datetime.now() -start).total_seconds()
    print(y)
    print(10, 'duration={}'.format(delta))
    
    

    注册代码 V2

    全局变量
    项目的settings.py文件实际上就是全局变量的配置文件。
    SECRET_KEY 一个强密码

    from django.http import JsonResponse,HttpRequest,HttpResponseBadRequest
    import simplejson,jwt,bcrypt
    from .models import User
    from django.db.models import Q
    from django.conf import settings
    
    
    def gen_token(user_id):  # 生成令牌;
        key = settings.SECRET_KEY
        return JsonResponse({
            'token':jwt.encode({'user_id':user_id},key,'HS256').decode()
        },status=201)
    
    # register
    def reg(request:HttpRequest):
        print(request.body)
    
        try:
            payload = simplejson.loads(request.body)  # 用户数据Json化 提交;
            print(type(settings))
    
            email = payload['email']      # 提取内容
            query = User.objects.filter(email=email)   # 看email是否已经存在;
            if query.first():  # 查一下: email 如果存在,则return error;
                print('============================')
                return HttpResponseBadRequest('用户名已存在')
    
            # 用户名不存在,继续向下;
            name = payload['name']   #
            password = payload['password']
    
            user = User()
            user.email = email
            user.name = name
            user.password = bcrypt.hashpw(password.encode(),bcrypt.gensalt())   # 密码采用bcrypt加密;
    
            try:
                user.save()    #保存到数据库test,唯一键约束
                return gen_token(user.id)   # 保存数据后返回一个令牌数据回去;
            # 可以返回user_id status=201(注册成功 重新登录) 或者 token(登录)
    
            except Exception as e:
                return JsonResponse({'reason':'asdaf'},status=400)
        except Exception as e:
            print(e)
            return HttpResponseBadRequest('参数错误')
    
    def show(request):          # 方法的使用方式各不相同;
        users = User.objects.all()
        print(users.values())# objects
        return JsonResponse({})
    # postman---------------------------------------------------------
    {
        "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo5fQ._qB1j7cV-TIe5nZY8yO_x0e3xsnPQef-_1SRcQM-3_k"
    }
    

    相关文章

      网友评论

          本文标题:58.4-密码安全问题和登录接口实现

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