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

2020-08-15  本文已影响0人  BeautifulSoulpy

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


总结:

  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
上一篇下一篇

猜你喜欢

热点阅读