我正在尝试将 Django 与非 ORM 数据源一起使用,并且在没有任何身份验证的情况下通过我的自定义后端访问其他资源时成功,现在我需要引入用户身份验证。没有本地数据库。当我收到请求(例如,使用用户名和密码发出的cURL命令(时,我需要对远程URL执行HTTP基本身份验证,成功后,我应该返回一个本地创建的用户对象,该对象只有一个用户名,没有什么花哨的。所以在我的 Tastypie 资源中,我写了这样的东西:
class dict2obj(object):
"""
Convert dictionary to object
@source http://stackoverflow.com/a/1305561/383912
"""
def __init__(self, d):
self.__dict__['d'] = d
def __getattr__(self, key):
value = self.__dict__['d'][key]
if type(value) == type({}):
return dict2obj(value)
return value
class RemoteAuth(Authentication):
def is_authenticated(self, request, **kwargs):
username = request.user.username
password = request.user.password
r = requests.get(AUTHENTICATION_URL, auth=(username, password))
if r.status_code == 200:
return True
return False
class UserResource(Resource):
username = fields.CharField(attribute='username')
class Meta:
resource_name = 'user'
authentication = RemoteAuth()
authorization = Authorization()
def obj_get_list(self, request=None, **kwargs):
result = []
posts.append(dict2obj(
{
'username': request.POST.get('username'),
}
))
return result
但这当然不起作用,因为身份验证对象无法像那样获取密码。请建议一种在不涉及任何本地数据库的情况下处理删除用户身份验证的好方法。
在不存储任何实际数据的情况下进行用户身份验证,那么您可以使用session
或作为最后的手段,cookies
.会话数据可以加密并存储在会话 Cookie 本身或侧面 Cookie 中。
这将如何运作?
您可以创建一个端点,例如api/v1/user/login
,作为处理用户身份验证/登录UserResource
方法。您可以像这样这样做:
def override_urls(self):
return [
url(r"^(?P<resource_name>%s)/login%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('user_login'), name="api_user_login"),
]
def user_login(self, request, **kwargs):
# Authentication process happens here.
return self.create_response(request, {})
要使上述功能正常工作,您必须导入tastypie.utils.trailing_slash
并django.conf.urls.url
。不幸的是,tastypie不支持任何帮助程序方法来减少创建URL的痛苦。
在 user_login
方法中,然后对针对远程终结点通过POST
传递的凭据进行身份验证,并将用户名和密码与任何特定于远程身份验证终结点的数据一起存储在request.session
中。在RemoteAuthentication
中,您可以检查会话密钥是否存在。
如果会话是本地文件系统中的数据,则可以认为内部的数据更安全一些。如果您决定将会话数据存储在加密的 Cookie 中,则必须为每个会话密钥存储一个值和一个校验和,可能存储在单个 Cookie 条目中,也可能存储在单独的 Cookie 条目中。
由于用户将以纯文本形式传递其凭据以登录,因此您可以考虑通过SSL提供user_login
视图(确保cookie未secure_only
(。