昨日内容回顾
# 1 接口文档的编写
-1 word,md 编写---->存放位置:存放共享文件平台,git上
-2 第三方的接口文档编写平台
-3 公司自己开发,使用开源搭建 yapi
-4 自动生成接口文档
-django+drf:swagger,coreapi
-FastAPI:自带自动生成接口文档
-接口文档应该有的东西
-接口描述
-请求地址
-请求方式
-请求编码格式
-请求参数(get请求参数,post,put请求参数)
-参数类型
-参数是否必填
-参数解释
-返回数据
-json格式示例
-重点参数解释
-错误码:写到全局
# 2 cookie,session,token发展历史
-会话保持
-cookie:存在于客户端浏览器的键值对
-session:存在于服务端的键值对(文件,内存,数据库。。。)
-token:三部分:头,荷载,签名
-签发:登录
-认证:登录后才能访问的接口
-认证类
-中间件
-装饰器
-别的位置
# 3 jwt:json web token:前后端认证的机制,token的web形式认证机制
# 4 base64
-jwt
-前后端交互:字符串--->base64编码
-图片:使用base64编码
# 5 django+drf如何使用jwt
-drf-jwt
# 6 快速签发
-配置一条路由--->帮咱们写了登录接口
# 7 定制返回格式
-写一个函数,返回什么,前端就看到什么
-配置文件中配置
# 8 jwt 的认证
-局部:视图类上
-认证类---->JSONWebTokenAuthentication
-权限类---->drf IsAuthenticated
-全局
-携带token
-请求头中
Authorization:jwt sadsfasdfasdf.asdfas'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300)df.asdfasdf
# jwt 配置问题
-记住的
-JWT_RESPONSE_PAYLOAD_HANDLER
-'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300)
-了解的
'JWT_AUTH_HEADER_PREFIX': 'JWT',
'JWT_SECRET_KEY': settings.SECRET_KEY,
-
drf-jwt源码执行流程(了解)
-
自定义用户表签发和认证
-
simpleui的使用
-
权限的控制(acl,rbac)
-
补充
1 drf-jwt源码执行流程(了解)
1.1 签发(登录)
# 登录接口,路由匹配成功,执行obtain_jwt_token---》post请求---》ObtainJSONWebToken的post方法
path('login/', obtain_jwt_token),
# ObtainJSONWebToken的post方法 继承APIView
def post(self, request, *args, **kwargs):
# 实例化得到序列化类
serializer = self.get_serializer(data=request.data)
# 做校验:字段自己,局部钩子,全局钩子
if serializer.is_valid():
# user:当前登录用户
user = serializer.object.get('user') or request.user
# 签发的token
token = serializer.object.get('token')
# 构造返回格式,咱们可以自定制---》讲过了
response_data = jwt_response_payload_handler(token, user, request)
response = Response(response_data)
if api_settings.JWT_AUTH_COOKIE:
expiration = (datetime.utcnow() +
api_settings.JWT_EXPIRATION_DELTA)
response.set_cookie(api_settings.JWT_AUTH_COOKIE,
token,
expires=expiration,
httponly=True)
#最终返回了咱们定制的返回格式
return response
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# 如何得到user,如何签发的token----》在序列化类的全局钩子中得到的user和签发的token
-JSONWebTokenSerializer---全局钩子---validate
#前端传入,校验过后的数据---》{"username":"lqz","password":"lqz1e2345"}
def validate(self, attrs):
credentials = {
# self.username_field: attrs.get(self.username_field),
'username':attrs.get('username')
'password': attrs.get('password')
}
if all(credentials.values()):
# auth 模块,authenticate 可以传入用户名,密码如果用户存在,就返回用户对象,如果不存就是None
# 正确的用户
user = authenticate(**credentials)
if user:
# 校验用户是否是活跃用户,如果禁用了,不能登录成功
if not user.is_active:
msg = _('User account is disabled.')
raise serializers.ValidationError(msg)
# 荷载----》通过user得到荷载 {id,name,email,exp}
payload = jwt_payload_handler(user)
return {
# jwt_encode_handler通过荷载得到token串
'token': jwt_encode_handler(payload),
'user': user
}
else:
msg = _('Unable to log in with provided credentials.')
raise serializers.ValidationError(msg)
else:
msg = _('Must include "{username_field}" and "password".')
msg = msg.format(username_field=self.username_field)
raise serializers.ValidationError(msg)
### 重点:
1 通过user得到荷载:payload = jwt_payload_handler(user)
2 通过荷载签发token:jwt_encode_handler(payload)
## 了解:
# 翻译函数,只要做了国际化,放的英文,会翻译成该国语言(配置文件配置的)
from django.utils.translation import ugettext as _
msg = _('Unable to log in with provided credentials.')
1.2 认证(认证类)
# JSONWebTokenAuthentication---->父类BaseJSONWebTokenAuthentication----》authenticate方法
def authenticate(self, request):
# 前端带在请求头中的token 值
jwt_value = self.get_jwt_value(request)
# 如果没有携带token,就不校验了
if jwt_value is None:
return None
try:
# jwt_value就是token
# 通过token,得到荷载,中途会出错
# 出错的原因:
-篡改token
-过期了
-未知错误
payload = jwt_decode_handler(jwt_value)
except jwt.ExpiredSignature:
msg = _('Signature has expired.')
raise exceptions.AuthenticationFailed(msg)
except jwt.DecodeError:
msg = _('Error decoding signature.')
raise exceptions.AuthenticationFailed(msg)
except jwt.InvalidTokenError:
raise exceptions.AuthenticationFailed()
# 如果能顺利解开,没有被异常捕获,说明token是可以信任的
# payload就可以使用,通过payload得到当前登录用户
user = self.authenticate_credentials(payload)
# 返回当前登录用户,token
return (user, jwt_value)
# jwt_value = self.get_jwt_value(request)
def get_jwt_value(self, request):
# 拿到了前端请求头中传入的 jwt dasdfasdfasdfa
# auth=[jwt,asdfasdfasdf]
auth = get_authorization_header(request).split()
# 'jwt'
auth_header_prefix = api_settings.JWT_AUTH_HEADER_PREFIX.lower()
if not auth:
# 请求头中如果没带,去cookie中取
if api_settings.JWT_AUTH_COOKIE:
return request.COOKIES.get(api_settings.JWT_AUTH_COOKIE)
return None
if smart_text(auth[0].lower()) != auth_header_prefix:
return None
if len(auth) == 1:
msg = _('Invalid Authorization header. No credentials provided.')
raise exceptions.AuthenticationFailed(msg)
elif len(auth) > 2:
msg = _('Invalid Authorization header. Credentials string '
'should not contain spaces.')
raise exceptions.AuthenticationFailed(msg)
return auth[1]
# 认证类配置了,如果不传jwt,不会校验,一定配合权限类使用
2 自定义用户表签发和认证
2.1 签发
视图层
from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
from rest_framework.viewsets import ViewSet
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import UserInfo
class UserView(ViewSet):
@action(methods=['POST'], detail=False)
def login(self, request, *args, **kwargs):
username = request.data.get('username')
password = request.data.get('password')
user = UserInfo.objects.filter(username=username, password=password).first()
if user:
# 登陆成功,签发token
# 通过user得到payload
payload = jwt_payload_handler(user)
# 通过payload得到token
token = jwt_encode_handler(payload)
return Response({'code': 1000, 'msg': '登陆成功', 'token': token})
else:
return Response({'code': 1001, 'msg': '用户名或密码错误'})
路由
from django.contrib import admin
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token
from rest_framework.routers import SimpleRouter
from app01.views import UserView
router = SimpleRouter()
router.register('user', UserView, 'user')
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', obtain_jwt_token),
]
urlpatterns += router.urls
标签:自定义,配置文件,JWT,jwt,token,user,msg,payload
From: https://www.cnblogs.com/super-xz/p/17120510.html