我有一个简单的REST API,需要从Web应用程序和远程服务访问。
远程服务通过包含API密钥的自定义HTTP标头进行身份验证。
如何保护该API,使得来自Web浏览器的请求受CSRF保护,但在通过API密钥进行身份验证时未执行CSRF检查?或者,一般来说,如何为特定视图上的某些请求启用CSRF保护,而不是其他请求?
目前,我有一个装饰器,用于检查API密钥的请求,并以这种方式对API用户进行身份验证:
# Regular auth
if request.user.is_authenticated():
# DO CSRF verification, then continue calling the view
elif 'HTTP_X_API_KEY' in request.META:
api_key = request.META['HTTP_X_API_KEY']
user = authenticate(username=settings.API_USER_NAME, password=api_key)
login(request, user)
# If user is authenticated and autzorized, continue calling the view
# but WITHOUT invoking CSRF protection
上述问题是,我只希望为普通用户提供CSRF保护,而不是API用户。
答案 0 :(得分:0)
好的,所以在经过一些修补之后,解决方案是禁用CSRF中间件并为需要CSRF保护的所有情况启用csrf_protect
。
这适用于API的特殊情况,因为无论如何都要对每个调用进行修饰,因此忽略某些视图的风险可以忽略不计。
然而,不的工作原理是使用csrf_exempt
。问题是装饰器只在视图上设置csrf_exempt
属性,如果你有多个装饰器,可能会再次被屏蔽,即使你使用functools.wraps
。
此外,由于csrf_exempt
在视图中放置了一个属性,因此无法根据请求的内容动态启用或禁用该属性 - 这实际上是非常静态的事情。