Token

  - 服务端会话技术
  - 理解为自定义的Session,但是由于sessiom有缺陷,因为依赖于cookie,cookie依赖于浏览器(有的浏览器不支持cookie)
  - **如果Web页面开发中,使用起来和Session基本一致**
  - **如果使用在移动端或客户端开发中,通常以Json形式传输**,需要移动端自己存储Token,需要获取Token关联数据的时候,主动传递Token

Cookie和Session,Token对比

  - Cookie使用更简洁,服务器压力更小,数据不是很安全
  - Session服务器要维护Session,相对安全
  - Token拥有Session的所有优点,自己维护略微麻烦,但支持更多的终端,不只是浏览器,也有手机客户端,或者桌面应用开发,这些本身不支持cookie,一旦不支持cookie所有的会话技术就挂了,所以产生了token

TOKEN实现了不依赖于cookie,来识别客户端,token在计算机身份认证中是令牌的意思,我们学习的是会话令牌,交互会话中唯一身份标识符。

实践:token实现用户登录

新建models:

from django.db import models


class Student(models.Model):
    s_name = models.CharField(max_length=16, unique=True)
    s_password = models.CharField(max_length=128)
    # 这里加token模型,因为还没有学缓存,按道理token应该加在缓存之中。
    s_token = models.CharField(max_length=256)

迁移模型至数据库

新建模板student_register.html用来做学生注册界面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>studentRegister</title>
</head>
<body>
<form action="{% url 'two:register' %}" method="post">
    <span>用户名</span><input type="text" name="username" placeholder="请输入用户名">
    <br>
    <span>密码:</span><input type="text" name="password" placeholder="请输入银行卡密码">
    <br>
    <button>注册</button>
</form>
</body>
</html>
  • span标签是超文本标记语言(HTML)的行内标签,被用来组合文档中的行内元素。
  • 标签用于为用户输入创建 HTML 表单。

      表单能够包含 input 元素,比如文本字段、复选框、单选框、提交按钮等等。
      表单还可以包含 menus、textarea、fieldset、legend 和 label 元素。
      表单用于向服务器传输数据。

  • br换行符

新建url

  url('^register', views.register, name='register')

新建views:

def register(request):
    if request.method =='GET':
        # 用来响应登陆界面
        return render(request, 'student_register.html')

    elif request.method == 'POST':
        # 用来接收客户端中的用户名密码
        username = request.POST.get('username')
        password = request.POST.get('password')

        try:
            # 用来在数据库中存储刚刚接收过来的用户名与密码
            student = Student()  # 实例化模型
            student.s_name = username  # 赋值给模型
            student.s_password = password
            student.save()  # 保存数据至数据库

        except Exception as e:
            # 只要发生了错误,重定向回到注册界面
            return redirect(reverse('two:register'))

        return HttpResponse('注册成功')

访问,点击注册:

返回注册成功
image.png
这时我们继续注册同样的用户名与密码
我们会发现,点击注册,仍然是注册界面

说明,用户名重复,注册发生了错误,进行了重定向

注册界面完成,接下来我们添加登录界面
url:

 url('^studentlogin', views.student_login, name='studentlogin'),

新建student_login.html作为登录页面
views:

def student_login(request):
    if request.method == 'GET':
        return render(request, 'student_login.html')
    elif request.method == 'POST':
        # 拿到用户名密码
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 获取ip地址

        # 在数据库中比对用户名和密码
        students = Student.objects.filter(s_name=username).filter(s_password=password)
        # 由于用户名唯一,只要匹配上就只有一个结果
        if students.exists():
            student = students.first()
        # 用户名密码匹配正确的用户端后,生成token
            ip = request.META.get('REMOTE_ADDR')
            token = generate_token(ip, username)
            # 将生成的token,保存到对应用户名的数据库中的s_token字段中
            student.s_token = token
            student.save()

            # 将自定义的token利用cookie返回到客户端中,也可以用jsonresponse进行返回
            response = HttpResponse('登陆成功')
            response.set_cookie('token', token)
            return response

        # 如果用户不存在,重定向
        return redirect(reverse('two:student_login'))


# 由于token要求唯一,在python  3.6以上有专门生成唯一token的方法,
# 我们也可以手动写函数生成唯一token
def generate_token(ip, username):
    # 时间,ctime返回的时间是字符串型
    c_time = time.ctime()
    # 由于并发量,两个人访问时间相同,我们还传入ip地址参数
    r = username
    # 将time,随机数,ip地址组合起来md5加密
    return hashlib.new('md5', (ip + c_time + r).encode('utf-8')).hexdigest()

hashlib.new(`'md5', (ip + c_time + r).encode('utf-8'))`是哈希对象
.hexdigest()是获取字符串

接着我们尝试登录刚刚注册的用户名:成功

而当我们错误登录时,会发现重定向回原来的界面

这时候我们新建url当作登录成功的个人中心:

url('^studentmine/', views.student_mine, name='studentmine'),

views:

# 显示个人中心
def student_mine(request):
    # 根据cookie查找到个人用户信息
    token = request.COOKIES.get('token')

    try:
        student = Student.objects.get(s_token=token)
    except Exception as e:
        return redirect(reverse('two:studentlogin'))
    # 登陆正常
    return HttpResponse(student.s_name)

访问,成功返回用户名

这个实践类似于我们手动将session模拟了出来,但这还是依赖于cookie
假如我们的客户端是移动端,没有cookie,我们可以采用jsonResponse来返回token
views修改如下:

def student_login(request):
    if request.method == 'GET':
        return render(request, 'student_login.html')
    elif request.method == 'POST':
        # 拿到用户名密码
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 获取ip地址

        # 在数据库中比对用户名和密码
        students = Student.objects.filter(s_name=username).filter(s_password=password)
        # 由于用户名唯一,只要匹配上就只有一个结果
        if students.exists():
            student = students.first()
        # 用户名密码匹配正确的用户端后,生成token
            ip = request.META.get('REMOTE_ADDR')
            token = generate_token(ip, username)
            # 将生成的token,保存到对应用户名的数据库中的s_token字段中
            student.s_token = token
            student.save()

            # 移动端  服务器将token利用responsed返回到客户端中
            data = {
                'status': 200,
                'msg': 'login success',
                'token': token
            }
            return JsonResponse(data=data)

        
        # 移动端用户登陆失败返参数
        data = {
            'status': 800,
            'msg': 'verify fail'
        }
        return JsonResponse(data=data)

# 由于token要求唯一,在python  3.6以上有专门生成唯一token的方法,
# 我们也可以手动写函数生成唯一token
def generate_token(ip, username):
    # 时间,ctime返回的时间是字符串型
    c_time = time.ctime()
    # 由于并发量,两个人访问时间相同,我们还传入ip地址参数
    r = username
    # 将time,随机数,ip地址组合起来md5加密
    return hashlib.new('md5', (ip + c_time + r).encode('utf-8')).hexdigest()


# 显示个人中心
def student_mine(request):

    # 服务器从移动端获取token
    token = request.GET.get('token')

    try:
        student = Student.objects.get(s_token=token)
    except Exception as e:
        return redirect(reverse('two:studentlogin'))
    # 登陆正常,移动端
    data = {
        'msg': 'ok',
        'status': 200,
        'data': {
            'username':student.s_name
        }
    }
    return JsonResponse(data=data)

接着我们用pycharm模拟移动端请求post

pycharm自带了测试工具


然而有坑,返回失败,我们还是用网页测试吧

然后访问studentmine/?token=


我们可以看到返回成功,这样就可以交给移动端的api.

最后修改:2024 年 03 月 13 日
如果觉得我的文章对你有用,请随意赞赏