1.安装
首次使用需要安装django-rest-framework及jwt相关包
pip install djangorestframework
pip install djangorestframework-simplejwt
2.settings文件增加配置
INSTALLED_APPS = [
'rest_framework',
'rest_framework_simplejwt'
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',), # 全局默认配置过滤
'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework_simplejwt.authentication.JWTAuthentication',],
'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticated',),
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': datetime.timedelta(hours=12),
'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=30),
'USER_ID_FIELD': "person_id",
# 此处id为生成token时使用自定义的用户表时会使用到,USER_ID_FIELD 是自定义用户表的id,不是id时 会报错user_id = getattr(user, api_settings.USER_ID_FIELD)
'SIGNING_KEY': JWT_SECRET_KEY,
'JWT_PUBLIC_KEY': JWT_SECRET_KEY,
'JWT_PAYLOAD_HANDLER': "person_name"
}
3.登录认证
1)在serializers中添加
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework import exceptions
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
"""
自定义登录认证,使用自有用户表
"""
username_field = 'person_name'
def validate(self, attrs):
password = ts.md5_encryption(attrs['password'])
authenticate_kwargs = {self.username_field: attrs[self.username_field], 'password': password}
try:
user = Person_info.objects.get(**authenticate_kwargs)
except Exception as e:
raise exceptions.NotFound(e.args[0])
refresh = self.get_token(user)
refresh["name"] = user.person_name
data = {"user_id": user.person_id, "token": str(refresh.access_token), "refresh": str(refresh)}
return data
2)models中添加
class Person_info(models.Model):
person_id = models.AutoField(primary_key=True)
person_name = models.CharField(verbose_name='姓名', max_length=32, unique=True)
password = models.CharField(verbose_name='密码', max_length=32, unique=True)
@property
def is_authenticated(self):
"""
Always return True. This is a way to tell if the user has been
authenticated in templates.
"""
return True
class Meta:
verbose_name = '个人信息'
verbose_name_plural = verbose_name
db_table = 'person_info'
3)在views中添加
from rest_framework_simplejwt.views import TokenObtainPairView
class FormulaTokenObtainPairView(TokenObtainPairView):
serializer_class = MyTokenObtainPairSerializer
4)url中配置
from django.contrib import admin
from django.urls import path,include
from bffile_data.views import FormulaTokenObtainPairView
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', FormulaTokenObtainPairView.as_view(), name='login')
]
ps1:如果想在自定义登录中间件,加上如下
1.在settings中添加配置
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'bffile_data.my_middleware.ExceptionChange'
]
2.新建my_middleware中定义
class ExceptionChange:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_template_response(self, request, response):
if hasattr(response, 'data'):
data = response.data
if isinstance(data, dict) is True:
if "detail" in data.keys():
# 用户名或密码错误
if data.get("detail") == "Person_info matching query does not exist.":
del response.data["detail"]
response.data["code"] = 402
response.data["msg"] = "用户名或者密码错误"
# 验证信息过期 token 过期
elif data.get("code") == "token_not_valid":
del response.data["detail"]
del response.data["messages"]
response.data["code"] = 401
response.data["msg"] = "登录已过期,请重新登录"
else:
del response.data["detail"]
response.data["code"] = 401
response.data["msg"] = "登录已过期,请重新登录"
return response
ps2:注册
1.在serializers中添加
class RegisterSerializer(serializers.ModelSerializer):
password_confirm = serializers.CharField(label='确认密码', help_text='确认密码',
min_length=6, max_length=20,
write_only=True,
error_messages={
'min_length': '仅允许6~20个字符的确认密码',
'max_length': '仅允许6~20个字符的确认密码', })
class Meta:
model = Person_info
fields = ('person_name', 'password', 'password_confirm')
extra_kwargs = {
'person_name': {
'label': '用户名',
'help_text': '用户名',
'min_length': 6,
'max_length': 20,
'error_messages': {
'min_length': '仅允许6-20个字符的用户名',
'max_length': '仅允许6-20个字符的用户名',
}
},
'password': {
'label': '密码',
'help_text': '密码',
'write_only': True,
'min_length': 6,
'max_length': 20,
'error_messages': {
'min_length': '仅允许6-20个字符的密码',
'max_length': '仅允许6-20个字符的密码',
}
}
}
# 多字段校验:直接使用validate,但是必须返回attrs
def validate(self, attrs):
if attrs.get('password') != attrs.get('password_confirm'):
raise serializers.ValidationError('密码与确认密码不一致')
user = Person_info.objects.filter(person_name=attrs.get('person_name')).first()
if user:
raise serializers.ValidationError('用户已经存在')
return attrs
2.新建tools文件定义公共方法
class Create_token(TokenObtainPairSerializer):
def validate(self, user):
refresh = self.get_token(user)
refresh["name"] = user.person_name
data = {"user_id": user.person_id, "token": str(refresh.access_token), "refresh": str(refresh)}
return data
3.在views中定义
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
class UserView(APIView):
def post(self, request):
ser_obj = RegisterSerializer(data=request.data)
if not ser_obj.is_valid():
result = ts.result_data(status.HTTP_200_OK, None, "用户已注册或用户名或密码不合法")
return Response(result)
password = ts.md5_encryption(request.data.get("password"))
user = models.Person_info.objects.create(person_name=request.data.get("person_name"),password=password)
token = ts.Create_token().validate(user)
result = ts.result_data(status.HTTP_200_OK, token, "注册成功")
return Response(result)```
4.在urls中定义
```python
from django.contrib import admin
from django.urls import path,include
from bffile_data.views import UserView
urlpatterns = [
path('admin/', admin.site.urls),
path('register/', UserView.as_view(), name='register')
]