2020/11/02:接口文档和注册功能
接口文档:
- URL
- 请求方式
- 请求数据的详细信息(数据类型,字段类型,字段意义)
- 返回数据的详细信息(数据类型,字段类型,字段意义)
单表的CURD:
URL:http://127.0.0.1:8000/a1/users/
请求方式:POST
请求信息:
username | age | home | height | classrooms |
---|---|---|---|---|
char | int | char | int | foreignkey |
Tony Stark | 38 | America | 185 | 1 |
返回数据:Json
{
"code":200,
"msg":"添加完成!"
}
URL:http://127.0.0.1:8000/a1/users/2/
请求方式:PUT
请求信息:
username | age | home | height | classrooms |
---|---|---|---|---|
char | int | char | int | foreignkey |
Thor | 1500~ | Asgard | 190 | 1 |
返回数据:
{
"code":200,
"msg":"修改成功!"
}
URL:http://127.0.0.1:8000/a1/users/
请求方式:GET
请求信息:无
返回数据:
{
{
"id": 1,
"username": "Tony Stark",
"age": 38,
"home": "America",
"height": 185,
"classrooms": {
"id": 1,
"class_name": "2001A",
"address": "教学楼4楼东侧"
},
"roles": []
},
...
}
URL:http://127.0.0.1:8000/a1/users/3/(删除ID为3的数据)
请求方式:GET
请求信息:无
返回数据:
{
"code":200,
"msg":"删除成功!"
}
model.py里User继承AbstractUser类:
AbstractUser是Django自带的登录、注册认证信息的用户模型类,继承之后会对原来的模型类进行改写
JWT
解决jwt单点登录:
- cookie + session + resis
- 登录服务器(SSO)
- jwt:header + payload + signature
header–头部:
声明类型,就是jwt;
声明方法,通常使用,HMAC SHA256加密
完整的头部:
{
'typ': "JWT",
'alg': "HS256"
}
// 之后头部进行base64加密(这个加密是可以对称密码的),构成第一部分
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
payload–载荷:
- 标准中注册声明
- 公共声明
- 私有声明
标准中注册的声明 (建议但不强制使用) :
- iss: jwt签发者
- sub: jwt所面向的用户
- aud: 接收jwt的一方
- exp: jwt的过期时间,这个过期时间必须要大于签发时间
- nbf: 定义在什么时间之前,该jwt都是不可用的.
- iat: jwt的签发时间
- jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
公共声明:公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.
私有的声明 : 私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。
定义一个payload:
{
'sub': "1234567890",
'name': "John Doe",
'admin': true
}
// 之后将数据进行二次加密,得到JWT的第二部分
eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6Ilx1NzJmY1x1NGViYSIsImV4cCI6MTYwNDQwNDgzNywiZW1haWwiOiIifQ.
signature(签证)做校验
JWT的第三部分是一个签证信息,这个签证信息由三部分组成:
- header (base64后的)
- payload (base64后的)
- secret
这个部分需要base64加密后的header和base64加密后的payload使用.
连接组成的字符串,然后通过header中声明的加密方式进行加盐secret
组合加密,然后就构成了jwt的第三部分。
// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, 'secret'); // czlw6ylTGmJXt18iz9-8qMRdJknoFZaV30Tp0ztGDRo
// 将这三部分连城一个完整的字符串,构成最终的jwt
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6Ilx1NzJmY1x1NGViYSIsImV4cCI6MTYwNDQwNDgzNywiZW1haWwiOiIifQ.czlw6ylTGmJXt18iz9-8qMRdJknoFZaV30Tp0ztGDRo
注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了
如何应用
一般是在请求头里加入Authorization
,并加上Bearer
标注:
fetch('api/user/1', {
headers: {
'Authorization': 'Bearer ' + token
}
})
服务端会验证token,如果验证通过就会返回相应的资源。整个流程就是这样的:
总结
优点
- 因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。
- 因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。
- 便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。
- 它不需要在服务端保存会话信息, 所以它易于应用的扩展
安全相关
- 不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。
- 保护好secret私钥,该私钥非常重要。
- 如果可以,请使用https协议