英文:
Why am I getting 403 for POST with DRF and rest_framework_api_key?
问题
I am getting a 403 response from the server in my new Django app. It is very simple. I don't even have models, I just want to return an audio file, but I want to do it through an API. Because of that, since I am not going to have users, I need an API key, and I found that I can use the Django REST framework and the REST framework API key modules. I have followed the quickstarts and can't seem to get a response. It was working before, but it was authenticating through CSRF, and like I said, it is going to be an API, so I won't have CSRF cookies.
Here is the view I am using:
@api_view(["POST"])
def tts_view(request):
data = request.POST
voice_name = data.get("voice_name")
text = data.get("text")
if not voice_name or not text:
return JsonResponse({"error": "Missing voice_name or text"}, status=400)
return JsonResponse({"wav": text_to_wav(voice_name, text)}, status=200, safe=False)
The settings:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework_api_key',
'TTS',
]
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',
]
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework_api_key.permissions.HasAPIKey",
]
}
And the fetch (the API key is just a test, so it doesn't matter):
fetch('/create-speech', {
method: 'POST',
body: JSON.stringify({
voice_name: "es-US-Neural2-B",
text: "Estoy feliz"
}),
headers: {
'Authorization': '0tSMNivu.f8DOBrHTTKfMQBGANNbjl5BJQcswN9ay',
'Content-Type': 'application/json'
}
})
.then((resp) => {
if (!resp.ok) throw Error(`${resp.statusText} - ${resp.status}`);
return resp.json();
})
.then((wav) => {
console.log('success');
});
I am doing the fetch in the console on the default page, which is not defined (like I said, I only want an API).
I have tried including rest_framework.permissions.AllowAny
into DEFAULT_PERMISSION_CLASSES
, but it doesn't work either.
I don't really know what else to do, so any help would be appreciated. Thanks!
英文:
I am getting a 403 response from the server in my new Django app. It is very simple. I don't even have models, I just want to return an audio file, but I want to do it through an API. Because of that, since I am not going to have users, I need an API key, and I found that I can use the Django REST framework and the REST framework API key modules. I have followed the quickstarts and can't seem to get a response. It was working before, but it was authenticating through CSRF, and like I said, it is going to be an API, so I won't have CSRF cookies.
Here is the view I am using:
@api_view(["POST"])
def tts_view(request):
data = request.POST
voice_name = data.get("voice_name")
text = data.get("text")
if not voice_name or not text:
return JsonResponse({"error": "Missing voice_name or text"}, status=400)
return JsonResponse({"wav": text_to_wav(voice_name, text)}, status=200, safe=False)
The settings:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework_api_key',
'TTS',
]
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',
]
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework_api_key.permissions.HasAPIKey",
]
}
And the fetch (the API key is just a test, so it doesn't matter):
fetch('/create-speech', {
method: 'POST',
body: JSON.stringify({
voice_name: "es-US-Neural2-B",
text: "Estoy feliz"
}),
headers: {
'Authorization': '0tSMNivu.f8DOBrHTTKfMQBGANNbjl5BJQcswN9ay',
'Content-Type': 'application/json'
}
})
.then((resp) => {
if (!resp.ok) throw Error(`${resp.statusText} - ${resp.status}`);
return resp.json();
})
.then((wav) => {
console.log('success');
});
I am doing the fetch in the console on the default page, which is not defined (like I said, I only want an API).
I have tried including rest_framework.permissions.AllowAny
into DEFAULT_PERMISSION_CLASSES
, but it doesn't work either.
I don't really know what else to do, so any help would be appreciated. Thanks!
答案1
得分: 1
来自Django REST Framework API Key文档:
默认情况下,客户端必须通过Authorization头传递其API密钥。它必须按照以下格式进行格式化:
Authorization: Api-Key <API_KEY>
你漏掉了Api-Key
部分(注意它与<API_KEY>
部分之间的空格)。因此,你的请求应该是:
fetch('/create-speech', {
...
headers: {
'Authorization': 'Api-Key 0tSMNivu.f8DOBrHTTKfMQBGANNbjl5BJQcswN9ay',
'Content-Type': 'application/json'
}
})
...
英文:
From the Django REST Framework API Key docs:
> By default, clients must pass their API key via the Authorization header. It must be formatted as follows:
>
> Authorization: Api-Key <API_KEY>
You're missing the Api-Key
part (notice the space between it and the <API_KEY>
part). So your request should be:
fetch('/create-speech', {
...
headers: {
'Authorization': 'Api-Key 0tSMNivu.f8DOBrHTTKfMQBGANNbjl5BJQcswN9ay',
'Content-Type': 'application/json'
}
})
...
答案2
得分: 0
你应该添加一个CSRF例外权限类或装饰器,例如:
from django.views.decorators.csrf import csrf_exempt
并且在你的API视图声明之前添加:
@api_view(["POST"])
@csrf_exempt
def tts_view(request):
有了这个,只要在API调用的标头中传递您的DRF API令牌,如下所示:
Authorization: Token token_string
就应该足够了。
英文:
You should add a CSRF exemption permission class or decorator, e.g.:
from django.views.decorators.csrf import csrf_exempt
and above your API view declaration:
@api_view(["POST"])
@csrf_exempt
def tts_view(request):
With this, ensuring that you pass in your DRF API token in headers in your API call as
Authorization: Token token_string
should suffice.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论