Dav*_*ave 4 django django-middleware python-3.x
我正在使用 Python 3.9 和 Django 3。我已经定义了这个中间件......
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',
'directory.middleware.extend_token_response.ExtendTokenResponse'
]
Run Code Online (Sandbox Code Playgroud)
但是,我不希望中间件应用于某个特定的 URL。我在中间件中对此进行了硬编码,如下所示
class ExtendTokenResponse:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
response = self.get_response(request)
if request.path != '/' + LOGOUT_PATH:
# Code to be executed for each request before
# the view (and later middleware) are called.
is_expired = True
try:
token = request.auth
print("req path: %s" % request.path)
is_expired = is_token_expired(token) if token else True
except Exception as err:
print(err)
if not is_expired:
Run Code Online (Sandbox Code Playgroud)
但这似乎有点草率,我认为中间件带有开箱即用的东西来配置它不需要应用于我的“/logout”路径。有没有更优雅的方式来配置它?
编辑:为了回应 Bernhard Vallant 的回答,我将中间件更改为以下内容
def token_response_exempt(view_func):
# Set an attribute on the function to mark it as exempt
def wrapped_view(*args, **kwargs):
return view_func(*args, **kwargs)
wrapped_view.token_response_exempt = True
return wraps(view_func)(wrapped_view)
Run Code Online (Sandbox Code Playgroud)
class ExtendTokenResponse: def init (self, get_response): self.get_response = get_response # 一次性配置和初始化。
def process_view(self, request, view_func, view_args, view_kwargs):
print("in process view method ...\n")
if getattr(view_func, "token_response_exempt", False):
print("returning none ...\n")
return None
# Code to be executed for each request before
# the view (and later middleware) are called.
is_expired = True
try:
token = request.auth
print("req path: %s" % request.path)
is_expired = is_token_expired(token) if token else True
except Exception as err:
print(err)
if not is_expired:
token.delete()
new_token = Token.objects.create(user = token.user)
# Code to be executed for each request/response after
# the view is called.
print("setting new token to %s" % new_token)
request.token = new_token
def __call__(self, request):
response = self.get_response(request)
print("---- in call method ----\n")
if getattr(request, "token", None) is not None:
print("setting refresh token header = %s" % request.token)
response['Refresh-Token'] = request.token
return response
Run Code Online (Sandbox Code Playgroud)
但对端点的任何调用,例如
curl --header "Content-type: application/json" --data "$req" --request POST "http://localhost:8000/login"
Run Code Online (Sandbox Code Playgroud)
导致没有从请求中检索到令牌。“request.auth”生成错误
'WSGIRequest' object has no attribute 'auth'
Run Code Online (Sandbox Code Playgroud)
Django 本身并没有为此提供解决方案。只要它是主要针对一个特定项目存在的中间件,在设置/中间件中硬编码/定义路径就可以了。
但是,如果您想标记某些视图以排除它们被处理,您可以使用装饰器,就像 Django 使用csrf_exempt装饰器一样。
from functools import wraps
def token_response_exempt(view_func):
# Set an attribute on the function to mark it as exempt
def wrapped_view(*args, **kwargs):
return view_func(*args, **kwargs)
wrapped_view.token_response_exempt = True
return wraps(view_func)(wrapped_view)
# your middleware
class ExtendTokenResponse:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
if getattr(request, "token", None) is not None:
response['Refresh-Token'] = request.token
return response
def process_view(self, request, view_func, view_args, view_kwargs):
if getattr(view_func, "token_response_exempt", False):
return None
# do your token generation here
request.token = token
Run Code Online (Sandbox Code Playgroud)
然后你可以使用装饰器,如下所示:
# urls.py
urlpatterns = [
path('logout/', token_response_exempt(LogOutView.as_view())),
]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2166 次 |
| 最近记录: |