1. settings.py
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = 'django-insecure-7jzbod!!(2p#zzimb$_=azn&%wlm2uvtp&=)ijx1&zmtsr^0av'
DEBUG = True
ALLOWED_HOSTS = ['*']
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app.apps.AppConfig',
'corsheaders',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
# 添加跨域处理中间件
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'app.middleware.TokenAuthenticationMiddleware',
]
# 跨域处理
CORS_ALLOW_CREDENTIALS = True # 允许携带身份凭证(如 Cookie)
CORS_ORIGIN_ALLOW_ALL = True # 设置为 True 表示允许所有跨域请求,不推荐在生产环境使用
CORS_ALLOW_ALL_ORIGINS = True # 允许所有 域名/IP 跨域
# CORS_ORIGIN_WHITELIST = ('http://127.0.0.1:*',) # 配置可跨域访问的 域名/IP
CORS_ALLOW_METHODS = ('*',) # 允许的 HTTP 请求方法 * 表示允许全部请求方法
# CORS_ALLOW_METHODS = (
# 'GET',
# 'POST',
# 'PUT',
# 'PATCH',
# 'DELETE',
# 'OPTIONS',
# ) # 允许的 HTTP 请求方法
CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
) # 允许的请求头
# CORS_EXPOSE_HEADERS = () # 允许前端访问的响应头
ROOT_URLCONF = 'rbacProject.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates']
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'rbacProject.wsgi.application'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'rbac_db',
'HOST': 'localhost',
'PORT': '3306',
'USER': 'root',
'PASSWORD': 'root',
'OPTIONS': {
'charset': 'utf8mb4',
'init_command': "SET time_zone='+8:00'",
},
}
}
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_TZ = True
STATIC_URL = 'static/'
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
'''jwt配置'''
#私钥
JWT_SECRET_KEY='8UhyuegyPYOFsqTPTX9FgLga4iYkssssLgggggggNQVn9jsasdhfaeYJXiS'
#TOKEN内容密钥 AES-128-ECB 偏移量0
# TOKEN_AES128_KEY = 'o0ubx1kB2V8aGq8L'
'''统一错误响应'''
#请求失败(默认)返回内容
# RES_DEFAULT_CONTENT = {'code':'9','data':{},'msg':'请求错误'}
'''请求前缀'''
#请求接口前缀 需要携带 /
# API_REQUEST_PREFIX = '/api'
'''安全认证相关'''
#无需token认证白名单列表
# NOT_TOKEN_PROCESS_ROUTE_LIST = [API_REQUEST_PREFIX+'/login']
NOT_TOKEN_PROCESS_ROUTE_LIST = ['/login','/register']
#IP白名单 长度大于0 表示启用
IP_ADDRESS_WHITE_LIST = []
#IP黑名单 长度大于0 表示启用
IP_ADDRESS_BLACK_LIST = []
2. urls.py
from django.contrib import admin
from django.conf.urls import url
from app.views import *
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', login),
url(r'^logout/', logout),
url(r'^register/', register),
url(r'^info/', get_info),
url(r'^paging/', paging),
]
3. result.py
from django.http import JsonResponse
# 封装返回json响应结果类
class Result:
@classmethod
def success(self, data=None, message="操作成功"):
return JsonResponse({
"code": 0,
"success": True,
"data": data,
"message": message
})
@classmethod
def error(self):
return JsonResponse({
"code": -1,
"success": False,
"data": None,
"message": "请求错误!"
})
@classmethod
def fail(self, message="操作失败"):
return JsonResponse({
"code": 1,
"success": False,
"data": None,
"message": message
})
4. baseModelMixin
import datetime
# 模型对象转成json对象基类
class BaseModelMixin:
def to_json(self, exclude=None):
fields = [f.name for f in self._meta.fields]
if exclude:
fields = [f for f in fields if f not in exclude]
data = {}
for f in fields:
value = getattr(self, f)
if isinstance(value, datetime.datetime):
value = value.strftime('%Y-%m-%d %H:%M:%S')
data[f] = value
return data
5. models.py
import datetime
from django.db import models
from utils.baseModelMixin import BaseModelMixin
import jwt
from rbacProject.settings import JWT_SECRET_KEY
# Create your models here.
class User(models.Model, BaseModelMixin):
username = models.CharField(max_length=30,unique=True,verbose_name='用户名')
password = models.CharField(max_length=255,verbose_name='密码')
email = models.EmailField(verbose_name='邮箱')
mobile = models.CharField(max_length=11,unique=True,verbose_name='手机号码')
create_time = models.DateTimeField(auto_now_add=True,null=True,verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True,null=True,verbose_name='更新时间')
def __str__(self):
return self.username
@property
def token(self):
return self._generate_jwt_token()
# 生成token
def _generate_jwt_token(self):
token = jwt.encode({
'exp': datetime.datetime.now(tz=datetime.timezone.utc) + datetime.timedelta(seconds=1*60*60*24),
'iat': datetime.datetime.now(),
'data': {
'username': self.username,
'user_id': self.id
}
}, JWT_SECRET_KEY, algorithm='HS256')
return token.decode('utf-8') # 将令牌转换为字符串类型
6. views.py
from django.contrib.auth import logout as auth_logout
from django.core.paginator import Paginator
from django.contrib.auth.hashers import make_password, check_password
from utils.result import Result
import json
from app.models import *
# Create your views here.
def login(request):
if request.method == 'POST':
try:
req_data = json.loads(request.body)
username = req_data['username']
password = req_data['password']
user = User.objects.get(username=username)
if check_password(password, user.password): # 使用 check_password 函数验证密码
token = user.token
token_ = {"token": token}
return Result.success(token_,"登录成功!")
else:
return Result.fail("用户名或密码错误!")
except (KeyError, User.DoesNotExist):
return Result.fail("用户名或密码错误!")
return Result.error()
def register(request):
if request.method == 'POST':
# 从请求中获取注册信息
req_data = json.loads(request.body)
username = req_data['username']
password = req_data['password']
email = req_data['email']
mobile = req_data['mobile']
try:
# 创建用户对象并保存到数据库
hashed_password = make_password(password) # 对密码进行加密
user = User(username=username, password=hashed_password, email=email, mobile=mobile)
user.save()
# 返回注册成功的响应
return Result.success("注册成功!")
except Exception as e:
# 处理注册过程中的异常情况
return Result.fail("注册失败!")
# 返回请求方式不允许的响应
return Result.error()
def logout(request):
if request.method == 'POST':
auth_logout(request) # 删除会话信息
# 返回成功响应
return Result.success("退出登录成功!")
return Result.error()
def get_info(request):
if request.method == 'GET':
user = request.user # 通过中间件已经验证过的用户对象
data = user.to_json(exclude=["password"])
return Result.success(data,"查询成功")
return Result.error()
def paging(request):
if request.method == 'POST':
# 获取前端传来的参数
req_data = json.loads(request.body)
per_page = req_data['per_page']
page = req_data['page']
users = User.objects.all()
paginator = Paginator(users, per_page)
page_data = [user.to_json(exclude=['password']) for user in paginator.page(page).object_list]
total_page = paginator.num_pages
total_count = paginator.count
data = {"records": page_data, "total_page":total_page, "total_count":total_count}
return Result.success(data)
return Result.error()
7. middleware.py
import jwt
from django.utils.deprecation import MiddlewareMixin
from app.models import User
from utils.result import Result
from rbacProject.settings import JWT_SECRET_KEY,NOT_TOKEN_PROCESS_ROUTE_LIST
'''
token认证中间件
'''
class TokenAuthenticationMiddleware(MiddlewareMixin):
def process_request(self, request):
# 检查请求的 URL 是否在白名单中,如果是,则跳过认证
if any([request.path.startswith(url) for url in NOT_TOKEN_PROCESS_ROUTE_LIST]):
return None
# 检查请求头中是否有 HTTP_AUTHORIZATION
if 'HTTP_AUTHORIZATION' not in request.META:
return Result.fail("未提供身份验证令牌!")
# 进行token认证
auth_header = request.META['HTTP_AUTHORIZATION']
try:
prefix, token = auth_header.split(' ')
if prefix == 'Bearer':
decoded_token = jwt.decode(token, JWT_SECRET_KEY, algorithms=['HS256'])
request.user = User.objects.get(id=decoded_token['data']['user_id'])
except jwt.exceptions.ExpiredSignatureError:
return Result.fail("token认证过期!")
except (ValueError, jwt.ExpiredSignatureError, jwt.InvalidTokenError, User.DoesNotExist):
return Result.fail("token认证无效!")
# token认证成功,放行
return None