Django,Djoser社交身份验证:在服务器端会话数据中找不到State.status_code 400



我正在用django和react实现一个身份验证系统。这两个应用程序分别在8000和3000端口上运行。我已经使用Djoser软件包实现了身份验证系统。这个包使用了一些依赖项social_core和social_django。一切似乎都配置好了。我点击登录谷歌按钮。。。我被重定向到谷歌登录页面,然后返回到3000端口的前端react应用程序,url上有状态代码参数。

现在,我将这些参数发布到后端。尝试验证状态的后端使用(social_core/backends/oauth.py)中的以下代码检查会话存储中是否存在状态密钥

def validate_state(self):
"""Validate state value. Raises exception on error, returns state
value if valid."""
if not self.STATE_PARAMETER and not self.REDIRECT_STATE:
return None
state = self.get_session_state()
request_state = self.get_request_state()
if not request_state:
raise AuthMissingParameter(self, 'state')
elif not state:
raise AuthStateMissing(self, 'state')
elif not constant_time_compare(request_state, state):
raise AuthStateForbidden(self)
else:
return state

由于某些原因,此时不存在状态会话密钥。。我收到一个错误,说在会话数据中找不到状态(下面的错误)

{"error":["State could not be found in server-side session data."],"status_code":400}

我回顾了我所做的所有行动:

  1. 向后端发出前端请求,以便为提供程序google-oauth2生成重定向url。通过这个操作,url被生成,状态密钥也被存储在具有特定值的会话中(google-oauth2_state)
  2. 前端接收url并重定向到google auth页面
  3. 使用谷歌进行身份验证,并在url上使用状态代码参数重定向回前端
  4. 前端获取数据表单url并将数据发布到后端,以验证接收到的状态是否等于点(1)上生成的状态

由于某些原因,状态代码没有持久化。。。任何想法和帮助都将不胜感激。

谢谢大家。

好的,所以这是使用社交身份验证时常见的问题。我多次遇到同样的问题。

流程

  1. http://127.0.0.1:8000/auth/o/google-oauth2/?redirect_uri=http://localhost:3000/(示例)发出请求

  2. 您将获得authorization_url。如果您注意到在authorizationurl中存在一个状态。这就是"服务器端的状态"。

  3. 现在您需要单击authorizationurl链接。然后你会得到谷歌认证页面。之后,您将被重定向到带有状态和代码的重定向url。请记住,此状态应与服务器端状态相同。(2)

  4. 向CCD_ 3发出post-req。如果你所在的州不一样,那么你就会遇到一些问题。

每次您想登录时,都需要向http://127.0.0.1:8000/auth/o/google-oauth2/?redirect_uri=http://localhost:3000/发出请求然后到CCD_ 5,从而得到相同的状态。

如果没有必要的详细信息,我只能说出两个可能的原因:

  1. 您使用不正确的session操作覆盖后端(或者用户在身份验证完成之前已注销)
  2. 前端使用了不正确的state参数

你可以在没有前端的情况下测试社交登录,比如说,如果你试图使用谷歌登录:

  1. 在浏览器中输入社交登录URL,如domain.com:8000/login/google-oauth2/
  2. 授权
  3. 查看页面是否正确重定向到默认登录页面

如果是,则可能需要检查前端代码,如果不是,则检查后端代码。

最后,如果你对潜在的风险不那么敏感,你也可以如下覆盖GoogleOAuth2类来禁用状态检查:

from social_core.backends import google
class GoogleOAuth2(google.GoogleOAuth2):
STATE_PARAMETER = False

最后,我已经到了一个地步,无论是在本地环境中还是在生产中,一切都能完美运行。核心问题原来与cookie和会话有关。正确的解决方案是欺骗后端服务器,使其将请求感知为来自"服务器";localhost:8000";而不是";localhost:3000";。这需要确保后端域保持一致。

要做到这一点,有两种可行的方法:

  1. 从服务器提供前端构建:服务器应托管前端的编译版本。通过这样做,前端将始终与后端共享相同的域。

  2. Django View with Google Auth Logic:实现一个简单的Django视图并将一个空模板与之关联。该模板应仅包含一个脚本标记,该标记包含管理Google身份验证所需的逻辑。该过程包括以下步骤:

    • 当用户点击";登录谷歌,";他们被引导到这个观点
    • 该视图管理身份验证过程,并在完成后检索访问令牌
    • 然后通过URL参数将访问令牌传递给前端

在我的情况下,我选择了第二种方法,因为它更适合我的需求。该过程包括创建基本视图并将其链接到样板。这样当用户选择";登录谷歌,";则触发相应的视图。随后,视图接管身份验证过程。一旦获得访问令牌,就会将其传输到指定的URL。

我认为您可能需要对步骤3和4中的流授权进行一些更改。

3.使用谷歌进行身份验证,并在url上使用状态和代码参数重定向回前端
4.Front-end获取数据表单url并将数据发布到后端,以验证接收到的状态是否等于点(1)上生成的状态。

也许你应该在谷歌授权后重定向回服务器端。

然后在服务器端进行检查!验证状态和代码(也许可以做更多的事情)。

然后让服务器重定向到您以前想要的前端站点。

由于某些原因,直接重定向到前端将错过参数..:-)

相关内容

  • 没有找到相关文章

最新更新