JWT的使用可以让两个组织之间传递可靠的信息(可以代替session认证机制),这是目前比较流行的跨域身份认证解决方案。
使用场景举例(对比session的好处):
普通网站基于session认证有弊端
- 因为session是存储在服务端的,需要一定的开销,在用户量很大的时候色session认证会降低服务器的性能,
- 再者,搭建分布式服务器情况下,用户访问时候,分配到的服务器不一定就是之前用户登录的那一台,这样的话获取session也比较麻烦
- 因为session是基于cookie来认证用户身份的,cookie被接获的话很容易造成跨域请求伪造的攻击(csrf)
这时候可以使用JWT来代替session从而解决这个弊端。
JWT的组成
Header: 描述JWT的基本信息,例如类型以及签名所用的算法,加密方式等。JSON内容经过Base64编码生成字符串成为Header
{
'typ':'JWT', # 声明类型
'alg': 'HS256', # 加密方式
}
然后使用Base64加密,形成字符串eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
PayLoad: 存放有效信息的地方,包含三部分
- 标准中注册声明:是由JWT标准定义的,建议是这么使用的
- iss:JWT的签发者
- sub:JWT所面向的用户
- aud:接受这个JWT的一方
- exp:JWT的过期时间(还有刷新时间)
- iat(issued at):签发时间
- 公共的声明 : 公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息。但不建议添加敏感信息,因为该部分在客户端可解密。
- 私有的声明 : 私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。
可以按照下面的定义:
{
'username': 'your_name',
'mobile': '134xxxxxxxx'
'email': 'xxx@xx.com'
'exp': '<有效时间>'
}
然后也用Base64加密得到第二部分eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
后面还有信息可以按照需求补充,JSON也是要经过Base64编码生成字符串成为PayLoad
signature:签名信息,防止JWT被伪造
1. 签名生成过程?
答:服务器在生成jwt token时,会将header和payload字符串进行拼接,用.隔开,然后使用一个只有服务
器知道的密钥对拼接后的内容进行加密,加密之后生成的字符串就是signature内容。
2. 签名验证过程?
答:当客户端将jwt token传递给服务器之后,服务器首先需要进行签名验证:
1)将客户端传递的jwt token中的header和payload字符串进行拼接,用.隔开
2)使用服务器自己的密钥对拼接之后的字符串进行加密
3)将加密之后的内容和将客户端传递的jwt token中signature进行对比,如果不一致,就说明
jwt token是被伪造的
基于JWT认证的工作流程
- 用户登陆到服务器
- 服务器验证用户信息
- 服务器验证通过后给用户生成一个token
- 用户端存储token,在下次访问的时候带上这个token
- 服务器验证token
JWT实际应用
在DRF框架中使用
pip install djangorestframework-jwt
安装好jwt包
配置项中加入jwt的配置信息
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
# 引入JWT认证机制,当客户端将jwt token传递给服务器之后
# 此认证机制会自动校验jwt token的有效性,无效会直接返回401(未认证错误)
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
# JWT扩展配置
JWT_AUTH = {
# 设置生成jwt token的有效时间
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
}
手动生成token
from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
也可以使用python的库中的jwt包生成token
使用pip install pyjwt
安装
具体的生成方法再去看看说明文档怎么使用