Django-oneall を使用して、サイトでソーシャルログインセッション認証を許可しています。 Django-rest-frameworkに推奨される認証プロバイダーの1つではありませんが、rest_framework.authentication.SessionAuthentication
はDjangoのデフォルトのセッション認証を使用します。だから統合はかなり簡単なはずだと思いました。
アクセス許可の面では、最終的にはIsAdmin
を使用しますが、開発目的のためにIsAuthenticated
に設定しただけです。それが403を返すとき、私はAllowAny
へのアクセス許可を緩和しましたが、まだサイコロはありませんでした。これが私の残りのフレームワーク設定です:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
# 'rest_framework.permissions.IsAuthenticated',
# 'rest_framework.permissions.IsAdminUser',
),
'PAGE_SIZE': 100,
'DEFAULT_FILTER_BACKENDS': (
'rest_framework.filters.DjangoFilterBackend',
),
}
編集:
私は以下の答えに基づいてこれを機能させました。 rest_framework
はcsrftoken
cookieと同じ値のX-CSRFToken
ヘッダーの両方を期待していることがわかりました。すべてのajaxリクエストに対してヘッダーを送信するようにフロントエンドコードを設定し、すべてが機能しました大丈夫。
Django RESTフレームワークは、いくつかの関連する状況下でステータスコード403
を返します:
DEFAULT_PERMISSION_CLASSES
が('rest_framework.permissions.IsAuthenticated',)
の場合に、認証されていないユーザーとしてAPIリクエストを行う。rest_framework.authentication.SessionAuthentication
を使用していて、CSRFTokenをリクエストセットに含めていません。テストAPIに対していくつかのデモリクエストを行い、それぞれの例を示して、発生している問題を診断し、解決方法を示します。 requests
ライブラリを使用します。
テストAPI
単一のフィールド(Life
、デフォルト値は42
)を含む単一のモデルanswer
を使用して、非常に単純なDRF APIをセットアップしました。これからのすべてはかなり簡単です。 ModelSerializer
-LifeSerializer
、ModelViewSet
-LifeViewSet
、DefaultRouter
を/life
URLルートに設定しました。 APIを使用し、SessionAuthentication
を使用するためにユーザーの認証を要求するようにDRFを構成しました。
APIを終了する
import json
import requests
response = requests.get('http://localhost:8000/life/1/')
# prints (403, '{"detail":"Authentication credentials were not provided."}')
print response.status_code, response.content
my_session_id = 'mph3eugf0gh5hyzc8glvrt79r2sd6xu6'
cookies = {}
cookies['sessionid'] = my_session_id
response = requests.get('http://localhost:8000/life/1/',
cookies=cookies)
# prints (200, '{"id":1,"answer":42}')
print response.status_code, response.content
data = json.dumps({'answer': 24})
headers = {'content-type': 'application/json'}
response = requests.put('http://localhost:8000/life/1/',
data=data, headers=headers,
cookies=cookies)
# prints (403, '{"detail":"CSRF Failed: CSRF cookie not set."}')
print response.status_code, response.content
# Let's grab a valid csrftoken
html_response = requests.get('http://localhost:8000/life/1/',
headers={'accept': 'text/html'},
cookies=cookies)
cookies['csrftoken'] = html_response.cookies['csrftoken']
response = requests.put('http://localhost:8000/life/1/',
data=data, headers=headers,
cookies=cookies)
# prints (403, '{"detail":"CSRF Failed: CSRF token missing or incorrect."}')
print response.status_code, response.content
headers['X-CSRFToken'] = cookies['csrftoken']
response = requests.put('http://localhost:8000/life/1/',
data=data, headers=headers,
cookies=cookies)
# prints (200, '{"id":1,"answer":24}')
print response.status_code, response.content
完全を期すために、DRFがコード403を返す状況がもう1つあります。urls.pyファイルのビュー宣言にas_view()
を追加し忘れた場合です。ちょうど私に起こり、問題がどこにあるかを見つけるまで何時間も費やしたので、この追加によって誰かの時間を節約できるかもしれません。
同じ問題を見つける可能性がある人のためだけに。次のようなルーターなしでビューセットを使用している場合:
user_list = UserViewSet.as_view({'get': 'list'})
user_detail = UserViewSet.as_view({'get': 'retrieve'})
Django Restフレームワークは、クラスレベルでpermission_classesを定義しない限り、403を返します。
class UserViewSet(viewsets.ModelViewSet):
"""
A viewset for viewing and editing user instances.
"""
permission_classes= YourPermisionClass
それが役に立てば幸い!