我正在尝试将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
但当然这不起作用,因为身份验证对象无法获得这样的密码。请建议一种处理删除用户身份验证的好方法,而不涉及任何本地数据库。
答案 0 :(得分:0)
如果您希望在不存储任何实际数据的情况下进行用户身份验证,那么您可以使用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条目中,也可以单独存储。
由于用户将以纯文本格式传递他们的凭据进行登录,因此您可以考虑通过SSL提供user_login
视图(确保cookie不是secure_only
)。