简体   繁体   English

无法使用 Symfony Guard 登录,可能是因为 cookie 和多域

[英]Can't login with Symfony Guard, maybe because of cookies & multidomain

I need a very simple form login, so I'm using a Symfony Guard authenticator for this.我需要一个非常简单的表单登录,所以我为此使用了 Symfony Guard 身份验证器。

My application is multi-domain, for now login is possible on only 3 of them (and 2 are subdomains).我的应用程序是多域的,现在只能在其中的 3 个(其中 2 个是子域)上登录。 But I can't log in on any of them.但我无法登录其中任何一个。

First, here are some resources:首先,这里有一些资源:

I don't understand why, but to debug this, I tried updating config/packages/dev/web_profiler.yaml to set intercept_redirects: true , to debug cookies and security config, and here's what I have when reproducing the common login scenario:我不明白为什么,但为了调试这个,我尝试更新config/packages/dev/web_profiler.yaml来设置intercept_redirects: true ,调试cookies和安全配置,这是我在重现常见登录场景时所拥有的:

  • When accessing the backend page (that shows the login form) I have the session cookie with a value like llno5smlmsema5nq02kr30s6m2 .当访问后端页面(显示登录表单)时,我的会话 cookie 的值类似于llno5smlmsema5nq02kr30s6m2
  • After I submit the form with correct values, I see the profiler's redirection page, and the Web Debug Toolbar shows me that I'm Logged in as Pierstoval and the session cookie sent by the response changes id and becomes b1vbcnvp7e6p0j0o0vtd7ui7bf (because by default the Firewall migrates the session when logging in), so this works.在我提交具有正确值的表单后,我看到了分析器的重定向页面,并且 Web 调试工具栏显示我Logged in as Pierstoval响应发送的会话 cookie 更改了 id 并变为b1vbcnvp7e6p0j0o0vtd7ui7bf (因为默认情况下防火墙在登录时迁移会话),所以这是有效的。 I can even see that the token is in the session.我什至可以看到令牌在会话中。 I also added dump() statements in the Session::save() method, and dumping session content shows the token.我还在Session::save()方法中添加了dump()语句,并且转储会话内容会显示令牌。 And the token is in the session file when I dump it too (in var/sessions/dev/sess_b1vbcnvp7e6p0j0o0vtd7ui7bf ).当我也转储它时,令牌也在会话文件中(在var/sessions/dev/sess_b1vbcnvp7e6p0j0o0vtd7ui7bf )。
  • I click on the http://back.esteren.docker/fr/ link showed by the redirection page, and then I see the session cookie id did not change (it's the one that have been set after logging in), but this time, the Web Debug Toolbar shows me that I'm Logged in as anon.我点击重定向页面显示的http://back.esteren.docker/fr/链接,然后我看到会话cookie id没有改变(这是登录后设置的),但这一次,Web 调试工具栏显示我Logged in as anon. . .

To me, there's a problem when the session is saved, so I took a look at the session files in var/sessions/dev/ , after the redirection .对我来说,保存会话时会出现问题,因此我查看了重定向后var/sessions/dev/中的会话文件。

When I cat var/sessions/dev/sess_b1vbcnvp7e6p0j0o0vtd7ui7bf , I see this:当我cat var/sessions/dev/sess_b1vbcnvp7e6p0j0o0vtd7ui7bf ,我看到:

_sf2_attributes|a:2:{s:18:"_csrf/authenticate";s:43:"bCm23vBGyrq52caehAH9cCTjJkAmdT9j9Z8yygaET78";s:26:"_security.main.target_path";s:30:"http://back.esteren.docker/fr/";}_sf2_meta|a:3:{s:1:"u";i:1538092899;s:1:"c";i:1538092750;s:1:"l";s:5:"86400";}

Which, when unserializing the session attribute bag array, gives this:其中,当反序列化会话属性包数组时,给出:

array:2 [
  "_csrf/authenticate" => "bCm23vBGyrq52caehAH9cCTjJkAmdT9j9Z8yygaET78"
  "_security.main.target_path" => "http://back.esteren.docker/fr/"
]

This means the token has not been saved in the session after the successful login.这意味着成功登录后令牌尚未保存在会话中。

And even worse: since I already debugged the session file before redirecting, I know that it was saved ni the session and at some time it was removed from it before the session being saved another time.更糟糕的是:因为我重定向之前已经调试了会话文件,所以我知道它是在会话中保存的,并且有时在会话再次保存之前从会话中删除

How is this even possible?这怎么可能? Did I forget something in my security configuration?我是否忘记了安全配置中的某些内容?

As a side-note, I tested with and without docker (with a plain php-fpm+nginx setup) and none worked, this probably means that it's not a permission issue from the docker side...作为旁注,我使用不使用 docker(使用普通的 php-fpm+nginx 设置)进行了测试,但没有任何效果,这可能意味着这不是 docker 方面的许可问题......

Finally, thanks to @Lynn and @Wirone on the public Symfony Slack channels, I ended up with a solution.最后,感谢公共 Symfony Slack 频道上的 @Lynn 和 @Wirone,我最终找到了一个解决方案。

First, the bug was the fact that my User entity (which is serialized in the session) did not store the password.首先,错误是我的 User 实体(在会话中序列化)没有存储密码。
And when a token is created, it checks if the "old" (in session) user password is the same as the "new" (refreshed) one, thanks to the Abstractoken::hasUserChanged() method .创建令牌时,它会检查“旧”(会话中)用户密码是否与“新”(刷新)用户密码相同,这要归功于Abstractoken::hasUserChanged()方法

And if the user object has changed, the firewall logs the user out .如果用户对象已更改,防火墙将用户注销

To fix this, either serialize the password with the user, or implement EquatableInterface and use your own checks.要解决此问题,请使用用户序列化密码,或实现EquatableInterface并使用您自己的检查。

And this is what I did:这就是我所做的:

  • Implement EquatableInterface实现EquatableInterface
  • Serialize only id and the timestampable fields createdAt and updatedAt连载只有id和timestampable领域createdAtupdatedAt
  • Make isEqualTo() check class and date fields to know if the user has changed.使isEqualTo()检查类和日期字段以了解用户是否已更改。

Hope this helps 👍希望这有帮助👍

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM