缺少所需的参数状态 Python 社交身份验证电子邮件验证

Missing needed parameter state Python social auth Email Validation

我在 Django 应用程序中使用 python 社交身份验证。在电子邮件验证中,邮件中收到的 link 在启动身份验证的同一浏览器中工作正常,但它在不同的 browser.Did 中显示 Missing needed parameter state 有人解决这个问题吗?

这里讨论这个问题Issue #577

这是因为其他浏览器没有部分管道数据!

Christopher Keefer 对此进行了 monkey-patch for this by fetching the session_key for Django session table. There's also a blog article here 研究,请参阅本文的第 3 步。

# Monkey patching - an occasionally necessary evil.
from social import utils
from social.exceptions import InvalidEmail

from django.core import signing
from django.core.signing import BadSignature
from django.contrib.sessions.models import Session
from django.conf import settings


def partial_pipeline_data(backend, user=None, *args, **kwargs):
    """
    Monkey-patch utils.partial_pipeline_data to enable us to retrieve session data by signature key in request.
    This is necessary to allow users to follow a link in an email to validate their account from a different
    browser than the one they were using to sign up for the account, or after they've closed/re-opened said
    browser and potentially flushed their cookies. By adding the session key to a signed base64 encoded signature
    on the email request, we can retrieve the necessary details from our Django session table.
    We fetch only the needed details to complete the pipeline authorization process from the session, to prevent
    nefarious use.
    """
    data = backend.strategy.request_data()
    if 'signature' in data:
        try:
            signed_details = signing.loads(data['signature'], key=settings.EMAIL_SECRET_KEY)
            session = Session.objects.get(pk=signed_details['session_key'])
        except BadSignature, Session.DoesNotExist:
            raise InvalidEmail(backend)

        session_details = session.get_decoded()
        backend.strategy.session_set('email_validation_address', session_details['email_validation_address'])
        backend.strategy.session_set('next', session_details.get('next'))
        backend.strategy.session_set('partial_pipeline', session_details['partial_pipeline'])
        backend.strategy.session_set(backend.name + '_state', session_details.get(backend.name + '_state'))
        backend.strategy.session_set(backend.name + 'unauthorized_token_name',
                                     session_details.get(backend.name + 'unauthorized_token_name'))

    partial = backend.strategy.session_get('partial_pipeline', None)
    if partial:
        idx, backend_name, xargs, xkwargs = \
            backend.strategy.partial_from_session(partial)
        if backend_name == backend.name:
            kwargs.setdefault('pipeline_index', idx)
            if user:  # don't update user if it's None
                kwargs.setdefault('user', user)
            kwargs.setdefault('request', backend.strategy.request_data())
            xkwargs.update(kwargs)
            return xargs, xkwargs
        else:
            backend.strategy.clean_partial_pipeline()
utils.partial_pipeline_data = partial_pipeline_data

这在很大程度上解决了问题,但仍然不完美。如果 session_key 在数据库中获取 deleted/changed,它将失败。每次会话数据更改时,Django 都会更新 session_key。因此,如果任何其他用户登录同一浏览器,session_key 会发生变化,并且用户无法通过电子邮件 link.

进行验证

Omab 在 issue

的评论中提到

I see the problem now, and even if I think that this could be solved with a re-write of the email validation pipeline, this affects all the pipeline functions that use the partial mechanism, so, I'm already working on a restructure of the pipeline serialization functionality that will improve this behavior. Basically the pipeline data will be dumped to a DB table and a hash code will be used to identify the processes which can be stopped and continue later, removing the dependency of the session.

正在寻找这方面的更新。