基于Token的身份验证

在实现登录功能的时候,正常的B/S应用都会使用cookie+session的方式来做身份验证,后台直接向cookie中写数据,但是由于移动端的存在,移动端是没有cookie机制的,所以使用token可以实现移动端和客户端的token通信。

验证流程

整个基于Token的验证流程如下:

  1. 客户端使用用户名跟密码请求登录
  2. 服务器收到请求,去验证用户名和密码
  3. 验证成功后,服务端会签发一个Token,再把这个Token发送到客户端
  4. 客户端收到的Token以后可以把它存储起来,比如放在Cookie或LocalStorage里
  5. 客户端每次向服务器发送其他请求的时候都要带着服务器签发的Token
  6. 服务器收到请求,去验证客户端请求里面带着的Token,如果验证成功,就像客户端返回请求的数据

JWT

构造Token的方法挺多的,可以说只要是客户端和服务器端约定好了格式,是想怎么写就怎么写的,然而还有一些标准写法,例如JWT读作/jot/,表示:JSON Web Tokens.

JWT标准的Token有三个部分:

  • header
  • payload
  • signature

    三个部分会用点分割开,并且都会使用Base64编码,所以真正的Token看起来像这样
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc

Header

header部分主要是两部分内容,一个是Token的类型,另一个是使用的算法,比如下面的类型就是JWT,使用的算法是HS256:

{
"typ": "JWT",
"alg": "HS256"
}

上面的内容要用 Base64 的形式编码一下,所以就变成这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Payload

Payload 里面是 Token 的具体内容,这些内容里面有一些是标准字段,你也可以添加其它需要的内容。下面是标准字段:

  • iss:Issuer,发行者
  • sub:Subject,主题
  • aud:Audience,观众
  • exp:Expiration time,过期时间
  • nbf:Not before
  • iat:Issued at,发行时间
  • jti:JWT ID

Signature

JWT的最后一部分是Signature,这部分相当于前两段的摘要,用来防止其他人来篡改Token中的信息,在处理时可以首先将前两段生成的内容使用Base64生成一下再加盐然后利用MD5等摘要算法在生成一遍

服务端生成Token

在服务端生成Token的时候,需要解决两个问题

  1. 使用什么加密算法
  2. Token如何存储

加密算法

这里的加密算法并不是MD5,SHA1这样的哈希算法,因为这种算法是无法解密的,只能用来生成摘要,在Django中内置了一个加密前面模块django.core.signing模块,可以用来加密和解密任何数据,使用签名模块的dumps和load函数来实现

示例:

from django.core import signing
value = signing.dumps({"foo":"bar"})
src = signing.loads(value)
print(value)
print(src)

结果:

eyJmb28iOiJiYXIifQ:1NMg1b:zGcDE4-TCkaeGzLeW9UQwZesciI
{‘foo’: ‘bar’}

Token如何存储

用什么存储

在服务器中Token可以存储在内存中,因为本质是字符串,所以并不会占用很大的内存空间,如果是分布式的存储可以将所有的token信息分段存储在不同的服务器中,也可以存储在数据库中,在Django中提供了缓存类,可以用来存储Token,Django的缓存可以结合Redis来使用,可以借助django-redis来实现

安装

pip install django-redis

配置

为了使用django-redis,需要将django cache setting修改,修改settings.py,默认是没有Cache的配置信息的,在其中添加:

CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}

当然,需要你首先安装了redis

cache使用

cache使用的时候基本可以使用set和get方法来进行存/取数据

>>> cache.set('my_key', 'hello, world!', 30)
>>> cache.get('my_key')
'hello, world!'

如何存

由于redis是使用k-v模式来进行存储数据的,我们可以使用用户名作为key,而token信息作为value,相较于直接使用token作为key的方式,好处是我们可以使用更少的空间实现一些功能,例如当用户修改了密码或点击注销之后,它的token可以直接失效,直接将该用户名所对应的数据删除就好了,或者用户在一次登录成功后,又一次请求了登录接口,我们可以很简单的更新该用户的token信息,而这样存储所依赖于我们的token可以进行解密,如果你是直接生成了一串无法解密的数据作为token,不能使用用户名作为token了

code

import time
from django.core import signing
import hashlib
from django.core.cache import cache HEADER = {'typ': 'JWP', 'alg': 'default'}
KEY = 'CHEN_FENG_YAO'
SALT = 'www.lanou3g.com'
TIME_OUT = 30 * 60 # 30min def encrypt(obj):
"""加密"""
value = signing.dumps(obj, key=KEY, salt=SALT)
value = signing.b64_encode(value.encode()).decode()
return value def decrypt(src):
"""解密"""
src = signing.b64_decode(src.encode()).decode()
raw = signing.loads(src, key=KEY, salt=SALT)
print(type(raw))
return raw def create_token(username):
"""生成token信息"""
# 1. 加密头信息
header = encrypt(HEADER)
# 2. 构造Payload
payload = {"username": username, "iat": time.time()}
payload = encrypt(payload)
# 3. 生成签名
md5 = hashlib.md5()
md5.update(("%s.%s" % (header, payload)).encode())
signature = md5.hexdigest()
token = "%s.%s.%s" % (header, payload, signature)
# 存储到缓存中
cache.set(username, token, TIME_OUT)
return token def get_payload(token):
payload = str(token).split('.')[1]
payload = decrypt(payload)
return payload # 通过token获取用户名
def get_username(token):
payload = get_payload(token)
return payload['username']
pass def check_token(token):
username = get_username(token)
last_token = cache.get(username)
if last_token:
return last_token == token
return False

非常详细的Django使用Token(转)的更多相关文章

  1. django CSRF token missing or incorrect

    django 异步请求时提示403 按照一般情况权限问题,python文件没有问题,仔细看了下response里有一句 CSRF token missing or incorrect.这个肯定是因为安 ...

  2. Django JWT Token RestfulAPI用户认证

    一般情况下我们Django默认的用户系统是满足不了我们的需求的,那么我们会对他做一定的扩展 创建用户项目 python manage.py startapp users 添加项目apps INSTAL ...

  3. django drf Token验证

    https://www.django-rest-framework.org/api-guide/authentication/#basicauthentication 1.INSTALLED_APPS ...

  4. Django restframework Token拥有不过期的认证

    REST框架中的Token认证不像Session认证一样,它是没有办法设置过期时间的,但是有时我们需要对Token做过期验证,比如说用户在A设备登陆之后获取一个Token,如果用户在没有清空浏览器缓存 ...

  5. Django (七) token&静态文件&媒体文件

    token&静态文件&媒体文件 1. token 1. 会话技术 2. 服务端会话技术 3. 它实际上就是手动实现的session 4. 实现token 4.1 在models.py中 ...

  6. jquery 设置django全局token

    通过JQUEYR中的ajaxSetup,来设置django中的token,即不需要再每次都去引用: 第一步: 先django中的html中设置 {%  csrf_token %} 第二步: 新一个js ...

  7. 很详细的Django入门详解

    Django 是用Python开发的一个免费开源的Web框架,可以用于快速搭建高性能,优雅的网站!采用了MVC的框架模式,即模型M,视图V和控制器C,也可以称为MVT模式,模型M,视图V,模板T.在学 ...

  8. django csrf token添加

    #views.py from django.shortcuts import render_to_response, RequestContext from django.views.decorato ...

  9. Django 序列化-token

    幂等性 幂等性:多次操作的结果和一次操作的结果是一样的 ,put请求是幂等的 post请求不是幂等的 序列化组件 全局和局部钩子函数 异常信息抛出过程 认证 路由里的,login.as_view() ...

随机推荐

  1. 聊聊C语言的预编译指令include

    "include"相信大家不会陌生,在我们写代码时,开头总会来一句"include XXX".include是干嘛用的,很多教材都提到了,因此这里不会再详细解释 ...

  2. Spring Cloud Alibaba | Sentinel: 服务限流基础篇

    目录 Spring Cloud Alibaba | Sentinel: 服务限流基础篇 1. 简介 2. 定义资源 2.1 主流框架的默认适配 2.2 抛出异常的方式定义资源 2.3 返回布尔值方式定 ...

  3. JAVA AES文件加解密

    AES加解密算法,代码如下: /** * Created by hua on 2017/6/30. */ import javax.crypto.Cipher; import javax.crypto ...

  4. [转载]nginx负载均衡+keepalived三主(多主)配置

    nginx负载均衡+keepalived三主(多主)配置 1.实验环境,实现目标三台主机分别配置nginx负载均衡对后端多台主机做转发,同时配置keepalived实现HA,保证任意主机出现故障时其他 ...

  5. 异步编程之Async,Await和ConfigureAwait的关系

    在.NET Framework 4.5中,async / await关键字已添加到该版本中,简化多线程操作,以使异步编程更易于使用.为了最大化利用资源而不挂起UI,你应该尽可能地尝试使用异步编程.虽然 ...

  6. NOIp 2018 普及&提高组试题答案

    你们考的咋样呢?在评论区说出自己的分数吧!

  7. Linux学习之安装jdk

    下载jdk for linux jdk for linux oracle download 卸载已有的jdk (1)查询是否安装java软件: rpm -qa|grep java (2)卸载jdk: ...

  8. [OpenGL] 不规则区域的填充算法

    不规则区域的填充算法 一.简单递归 利用Dfs实现简单递归填充. 核心代码: // 简单深度搜索填充 (四连通) void DfsFill(int x, int y) { || y < || x ...

  9. python初步编写用户登录

     python初步编写用户登录 python编写用户登录 用python写一个脚本,使得这个脚本在执行后,可以产生如下的效果: 1.用户的账号为:root 密码为:westos 2.用户账号和密码均输 ...

  10. GitLab-CI 来自动创建 Docker 镜像

    1.what is gitlab-ci docker image CI/CD 自动化集成,自动化部署.简单的说就是把代码提交到gitlab管理的同时部署到指定的server,打成docker imag ...