美文网首页
58.5-登录功能实现和认证装饰器

58.5-登录功能实现和认证装饰器

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

    不要妄想事情变得简单,还是期待自己能做的更好吧!


    总结:

    1. 网络安全是一个很有前途的方向;
    2. session和cookie是解决无状态的问题(用户来了);
    3. 用户密码加密不在用户端加密;

    用户功能设计与实现

    提供用户注册处理
    1. 提供用户登录处理
    2. 提供路由配置
    1. 用户登录接口设计

    接收用户通过POST方法提交的登录信息,提交的数据是JSON格式数据
    Restful=URL+METHOD URL:/user/reg ; METHOD:POST

    从user表中email找出匹配的一条记录,验证密码是否正确。
    验证通过说明是合法用户登录,显示欢迎页面。
    验证失败返回错误状态码,例如4xx

    {
    "password":"abc",
    "email":"wayne@magedu.com"
    }
    
    1.1 路由配置
    from django.conf.urls import url
    from .views import reg,show,login
    
    urlpatterns = [
        url(r'^reg$',reg),
        url(r'^login$',login),
        url(r'^show$',show),
    ]
    
    1.2 登录代码
    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 login(request:HttpRequest):
        try:
            payload = simplejson.loads(request.body)
            email = payload['email']
            password = payload['password']
    
            user = User.objects.filter(email=email).first()
            if user:
                if bcrypt.checkpw(password.encode(),user.password.encode()):
                    return gen_token(user.id)
                else:
                    return HttpResponseBadRequest('登录失败3')
            else:
                return HttpResponseBadRequest('登录失败1')
    
    
        except Exception as e:   # 记录登录日志;
            print(e)
            return HttpResponseBadRequest('登录失败2')
    
    def show(request):          # 方法的使用方式各不相同;
        users = User.objects.all()
        print(users.values())# objects
        return JsonResponse({})
    #---------------------------------------------------
    {
        "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo4fQ.-c9iliH6cV9PmsnxL-73ptlIetVsWvA-dUG5MBcboOU"
    }
    
    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 jwt.encode({'user_id':user_id},key,'HS256').decode()
    
    # 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 JsonResponse({
                    'user_id':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 login(request:HttpRequest):
        try:
            payload = simplejson.loads(request.body)
            email = payload['email']
            password = payload['password']
    
            user = User.objects.filter(email=email).first()
            if user:
                if bcrypt.checkpw(password.encode(),user.password.encode()):
                    token = gen_token(user.id)
                    res = JsonResponse({
                        'user':{
                            'user_id': user.id,
                            'name': user.name,
                            'email': user.email
                        }, 'token': token
                    })
    
                    res.set_cookie('jwt',token)  # 演示 如何 set_cookie
    
                    return res
                else:
                    return HttpResponseBadRequest('登录失败3')
            else:
                return HttpResponseBadRequest('登录失败1')
    
    
        except Exception as e:   # 记录登录日志;
            print(e)
            return HttpResponseBadRequest('登录失败2')
    
    def show(request):          # 方法的使用方式各不相同;
        users = User.objects.all()
        print(users.values())# objects
        return JsonResponse({})
    # --------------------------------------------------------
    {
        "user": {
            "user_id": 8,
            "name": "sunny",
            "email": "sunny@magedu.com"
        },
        "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo4fQ.-c9iliH6cV9PmsnxL-73ptlIetVsWvA-dUG5MBcboOU"
    }
    
    2. 认证接口

    如何获取浏览器提交的token信息?
    1、使用Header中的Authorization
    通过这个header增加token信息。
    通过header发送数据,方法可以是Post、Get

    2.自定义header
    JWT来发送token
    我们选择第二种方式

    认证

    基本上所有的业务都需要认证用户的信息。
    在这里比较时间戳,如果过期,就直接抛未认证401,客户端收到后就该直接跳转到登录页。
    如果没有提交userid, 就直接重新登录。如果用户查到了, 填充user对象。
    request时间戳比较->userid比较>向后执行

    def show(request):          # 方法的使用方式各不相同;
        token = request.META.get('HTTP_JWT', None)
        # print(list(filter(lambda x: x.lower().endswith('jwt'),meta)))  #查询 http_jwt
        print(token)
        key = settings.SECRET_KEY
        try:
            jwt.decode(token,key,algorithms=['HS256'])  # 解失败,被改过;接成功;没改过;
            print(payload)
        except Exception as e:
            print(e)
            return HttpResponseBadRequest('用户名密码错误')
    
        return JsonResponse({'status':'ok'})
    
    from django.http import JsonResponse,HttpRequest,HttpResponseBadRequest
    import simplejson,jwt,bcrypt,datetime
    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 jwt.encode({'user_id':user_id,
                           'timestamp':int(datetime.datetime.now().timestamp())
                           },key,'HS256').decode()
    
    # 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 JsonResponse({
                    'user_id':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 login(request:HttpRequest):
        try:
            payload = simplejson.loads(request.body)
            email = payload['email']
            password = payload['password']
    
            user = User.objects.filter(email=email).first()
            if user:  # 登录成功,返回信息
                if bcrypt.checkpw(password.encode(),user.password.encode()):
                    token = gen_token(user.id)
                    res = JsonResponse({
                        'user':{
                            'user_id': user.id,
                            'name': user.name,
                            'email': user.email
                        }, 'token': token
                    })
    
                    res.set_cookie('jwt',token)  # 演示 如何 set_cookie
    
                    return res
                else:
                    return HttpResponseBadRequest('登录失败3')
            else:
                return HttpResponseBadRequest('登录失败1')
    
        except Exception as e:   # 记录登录日志;
            print(e)
            return HttpResponseBadRequest('登录失败2')
    # 谁认证就给谁加装饰器;
    def auth(view_func):
        def wrapper(request:HttpRequest):
            token = request.META.get('HTTP_JWT', None)  # 拿到http_jwt 字典的值
            # print(list(filter(lambda x: x.lower().endswith('jwt'),meta)))  #查询 http_jwt
            print(token)
            key = settings.SECRET_KEY
            try:
                print('=============================')
                jwt.decode(token, key, algorithms=['HS256'])  # 解失败,被改过;接成功;没改过;
                print(payload)
                user = User.objects.filter(pk=payload['user_id']).first()   # 查询一次数据库;
                # user = User.objects.filter(pk=payload['user_id']).filter(isactive=True).first()
    
                if user: # 拿到user,
                    request.user = user  #request 动态添加属性;
                    ret = view_func(request)
    
                    return ret
                else:
                    return HttpResponseBadRequest('1用户名密码错误')
            except Exception as e:
                print(e)
                return HttpResponseBadRequest('2用户名密码错误')
    
        return wrapper
    
    @auth        # 认证拦截
    def show(request):          # 方法的使用方式各不相同;
        print(request.user,'---------------------------')
        return JsonResponse({'status':'ok'})
    #----------------------------------------------------------
    {
        "user": {
            "user_id": 8,
            "name": "sunny",
            "email": "sunny@magedu.com"
        },
        "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo4LCJ0aW1lc3RhbXAiOjE1OTc1MDE3NDIuODYxNzA3fQ.jOOTyLE6GeXMmdCmYhGmw5fjj2BQoHWPmtx8ppvYUrU"
    }
    
    post 提取cookie - session

    相关文章

      网友评论

          本文标题:58.5-登录功能实现和认证装饰器

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