gpt4 book ai didi

django - 让 Django 后端接受前端的 SHA256 而不是纯文本密码

转载 作者:行者123 更新时间:2023-12-03 02:59:03 25 4
gpt4 key购买 nike

我国政府限制了 HTTPS 速度,以阻止访问伊朗境外的安全网络服务。现在我的客户因登录他们的帐户而感到痛苦。我知道当前帐户密码是使用 pbkdf2_sha256 算法进行加密和加盐的,并且有一些 javascript/jQuery 库可以消化 sha256 哈希值。

我的问题:是否有任何简单的方法(不需要重写/更改原始django.contrib.auth)来使用AJAX请求发送的sha256哈希值作为登录密码?

更新:我计划在伊朗境内托管我的网站(伊朗的费用是伊朗的 5 倍,当然由政府控制),但至少 HTTPS 协议(protocol)不受限制。无论如何,通过 HTTP channel 以纯文本或摘要方式发送密码都是不安全的。虽然作为一名网络开发人员(而不是网络专家),我认为他们可以随时收集/嗅探哈希值/ session ID/cookie,但解决问题需要复杂的知识和努力,毕竟我的网站不需要这种级别的安全性。我们生活在不同的星球。

最佳答案

您可以编写自己的身份验证后端来使用原始密码:

from django.contrib.auth import backends
from django.contrib.auth.models import User

class RawPasswordUser(User):
class Meta:
proxy = True

def set_password(self, raw_password):
# default implementation made a hash from raw_password,
# we don't want this
self.password = raw_password

def check_password(self, raw_password):
# same here, don't make hash out of raw_password
return self.password == raw_password

class ModelBackend(backends.ModelBackend):
def authenticate(self, username=None, password=None):
try:
user = RawPasswordUser.objects.get(username=username)
if user.check_password(password):
return user
except RawPasswordUser.DoesNotExist:
return None

def get_user(self, user_id):
try:
return RawPasswordUser.objects.get(pk=user_id)
except RawPasswordUser.DoesNotExist:
return None

在设置文件中:

AUTHENTICATION_BACKENDS = (
# ModelBackend from project_root/auth/backends.py
'auth.backends.ModelBackend',
)

现在,当您在 View 中验证用户时,您将获得RawPasswordUser实例。这同样适用于 login_required 装饰器,request.user 将指向代理类。

参见documentation了解详情。

对于 Django 1.5+ there is also an option要将默认用户模型替换为自定义模型,但要保留现有用户,您必须以某种方式迁移它们,请参阅 this question .

<小时/>

实际上,您无法保持用户密码不变。

默认情况下,Django 按以下格式存储密码:

algorithm$iterations$salt$hash

这意味着:

  • 您不能仅根据原始密码的哈希值重新生成密码,因为您没有原始密码。

  • 如果不知道盐,您也将无法在客户端生成相同的哈希值。您可以将其传递给客户端,但 salt 应该是一个 secret ,因此通过未加密的 channel 进行传递是不明智的。

我看到的最简单的解决方案是保持当前的 Django 行为,正如 Tadeck 所建议的那样。在评论中,在客户端添加哈希并强制用户更改密码。

嗯,这并不是一个真正的解决方案,因为攻击者可以拦截消化后的密码并直接使用它们,但您提到了您的问题更新。既然你不太关心安全性,你也可以查看 public key encryption在 JavaScript 中。

<小时/>

Tadeck 提出的另一个解决方案是使用类似 OAuth 的服务,它可能看起来有点像这样:

def index(request):
access_token = request.REQUEST.get('token', None)
if not access_token:
return redirect('login')

# Custom authentication backend that accepts a token
# and searches for a user with that token in database.
user = authenticate(access_token)
if not user:
return redirect('login')

return render(...)

def auth(request):
''' This ajax-view has to be encrypted with SSL.'''
# Normal Django authentication.
user = authenticate(request.POST['username'], request.POST['password'])

# Authentication failed
if user is None:
return json.dumps({'error': '...'})

# generate, save and return token in json response
token = UserToken(user=user, value=generate_token())
# token.expires_at = datetime.now() + timedelta(days=1)
token.save()

return json.dumps({'token': token.value})

受到攻击的人仍然可以拦截访问 token ,但这比拦截密码哈希要好一些。

关于django - 让 Django 后端接受前端的 SHA256 而不是纯文本密码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16339174/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com