我的网站通过用户可以在其个人资料页面上设置的PGP公钥使用2因子身份验证机制。 效果很好,但是由于我实施了单会话策略,因此我在这里找到了:How to prevent multiple login in Django <-我的2FA页面返回
PGPMessage类型的对象不可JSON序列化
这种行为在我更改后立即出现:
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
到
SESSION_ENGINE = "django.contrib.sessions.backends.db"
在settings.py。因此,我想我只是无法正确处理会话,但是为什么我能够从缓存中获取所有需要的数据,而不是从settings.py中配置的数据库中获取所有必需的数据呢?
models.py
class UserSession(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
session = models.OneToOneField(Session, on_delete=models.CASCADE)
signals.py
from django.contrib.auth import user_logged_in
from django.contrib.sessions.models import Session
from django.dispatch.dispatcher import receiver
from .models import UserSession
@receiver(user_logged_in)
def remove_other_sessions(sender, user, request, **kwargs):
# remove other sessions
Session.objects.filter(usersession__user=user).delete()
# save current session
request.session.save()
# create a link from the user to the current session (for later removal)
UserSession.objects.get_or_create(
user=user,
session=Session.objects.get(pk=request.session.session_key)
)
views.py
def 2fa(request):
if request.method == 'POST':
form = Login2faForm(request.POST)
if form.is_valid():
if request.POST['token'] == request.session['token']:
user = User.objects.get(id=request.session['userID'])
hybridlogin(request, user)
return redirect(reverse('home'))
else:
encrypted_token_message = request.session['encrypted_token']
messages.error(request, 'Wrong Login Code, Please try again.')
return render(request, 'Accounts/2fa.html', {'form': Login2faForm(), 'token': str(encrypted_token_message)}
)
else:
encrypted_token_message = request.session['encrypted_token']
messages.error(request, 'Wrong Login Code, Please try again.')
return render(request, 'Accounts/2fa.html', {'form': Login2faForm(), 'token': str(encrypted_token_message)})
else:
token = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(30))
token_message = token
if 'token' not in request.session:
request.session['token'] = token
user = User.objects.get(id=request.session['userID'])
if 'encrypted_token' not in request.session:
encryption_key = PGPKey.from_blob(user.pubpgp.rstrip("\r\n"))[0]
encrypted_token_message = encryption_key.encrypt(PGPMessage.new(token_message), cipher=SymmetricKeyAlgorithm.AES256)
request.session['encrypted_token'] = encrypted_token_message
else:
encrypted_token_message = request.session['encrypted_token']
return render(request, 'Accounts/2fa.html', {'form': Login2faForm(), 'token': str(encrypted_token_message)})
由于我将会话后端更改为数据库,以便单一登录策略正常工作,所以我猜以下行得到错误处理:
user = User.objects.get(id=request.session['userID'])