国际化路由不适用于安全访问控制
Internationalized routing don't work fine with security access controls
我正在尝试使用 Internationalized routing。
所以对于一条路线很多 URLs。
但有一条路线仍由其名称唯一标识。
这是一个很棒的功能,但文档没有说明如何处理安全组件。
事实上,我正在使用 url to make a basic secure of the app。
但是由于每个 URL 在区域设置上可能不同,我发现让事情仍然有效的唯一方法是复制尽可能多的路径名称。
这是我现在的 security.yaml
:
# ./config/packages/security.yaml @ line 27 -- 41
access_control:
# Allow every user to visit index_no_locale page (Default page when no locale is selected).
# This will redirect to login page with default locale.
- { path: ^/$, roles: IS_AUTHENTICATED_ANONYMOUSLY}
# Allow anonymous to visit login page.
- { path: ^(/en/login|/fr/connexion|/de/verbindung), roles: IS_AUTHENTICATED_ANONYMOUSLY}
# Allow anonymous to visit password_reset page.
- { path: ^(/en/password/reset|/fr/mot-de-passe/reinitialisation|/de/passwort/zurücksetzen), roles: IS_AUTHENTICATED_ANONYMOUSLY}
# Allow anonymous to visit email_send_password_forgot
- { path: ^(/en/email/send/password/forgot|/fr/courriel/envoyer/mot-de-passe|/de/email/schreiben/passwort/vergessen), roles: IS_AUTHENTICATED_ANONYMOUSLY}
# Allow only admin to visit admin url
- { path: ^/admin, roles: IS_ADMIN}
# Allow authenticated user ONLY to visit every other urls
# Specific user right controls are managed inside controller
- { path: ^/, roles: IS_AUTHENTICATED_FULLY}
正如我所说,这是可行的,但我必须为每条现有路线复制路径。
我让你看看路线以便更好地理解:
> php bin/console debug:router
Name Method Scheme Host Path
-------------------------------- -------- -------- ------ --------------------
password_reset.en ANY ANY ANY /{_locale}/password/reset/{user_id}/{token_value}
password_reset.fr ANY ANY ANY /{_locale}/mot-de-passe/reinitialisation/{user_id}/{token_value}
password_reset.de ANY ANY ANY /{_locale}/passwort/zurücksetzen/{user_id}/{token_value}
login.en ANY ANY ANY /{_locale}/login
login.fr ANY ANY ANY /{_locale}/connexion
login.de ANY ANY ANY /{_locale}/verbindung
logout ANY ANY ANY /{_locale}/logout
index_no_locale ANY ANY ANY /
...
我真的不喜欢这个,因为每次必须添加或修改 URL 时都会对 opeer 进行冗余修改。
主要问题是当用户未登录并访问需要 IS_AUTHENTICATED_FULLY
角色的 URL 时。
所以现在 'Voter' 表示访问被拒绝并将响应重定向到 login_path 定义为 security.yaml
问题来了。我无法定义 login_path 的正确路径,因为我无法猜测用户使用的语言环境是什么。所以我对此进行了硬编码:
# ./config/packages/security.yaml @ line 1 -- 21
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
...
firewalls:
dev:
...
main:
anonymous: true
form_login:
login_path: /en/login
check_path: /en/login
provider: my_provider
logout:
path: /en/logout
guard:
...
实际上注销也一样...
据此https://symfony.com/doc/current/security.html#logging-out
您可以让 security.firewalls.main.logout.path
引用路由名称。至于登录,您也可以参考路由名称,但推荐的方法是使用 guard authenticators 参见 https://symfony.com/doc/current/security/form_login.html.
编辑:
至于 access_control
,当我查看 Symfony\Component\HttpFoundation\RequestMatcher
中的代码时,它不会查找路由名称。所以我看到了两个选项。
- 你找到了一种方法来创建你自己的 RequestMatcher 并让 Symfony 使用它,在我看来,这对于你需要的东西来说似乎过于复杂了。
- 为您现在正在做的
access_control
中的每个语言环境创建一个条目。为了更好的可读性,我通常会把每个条目放在自己的行上,而不是像你那样使用正则表达式 or
,但我就是这样。
我正在尝试使用 Internationalized routing。
所以对于一条路线很多 URLs。
但有一条路线仍由其名称唯一标识。
这是一个很棒的功能,但文档没有说明如何处理安全组件。
事实上,我正在使用 url to make a basic secure of the app。
但是由于每个 URL 在区域设置上可能不同,我发现让事情仍然有效的唯一方法是复制尽可能多的路径名称。
这是我现在的 security.yaml
:
# ./config/packages/security.yaml @ line 27 -- 41
access_control:
# Allow every user to visit index_no_locale page (Default page when no locale is selected).
# This will redirect to login page with default locale.
- { path: ^/$, roles: IS_AUTHENTICATED_ANONYMOUSLY}
# Allow anonymous to visit login page.
- { path: ^(/en/login|/fr/connexion|/de/verbindung), roles: IS_AUTHENTICATED_ANONYMOUSLY}
# Allow anonymous to visit password_reset page.
- { path: ^(/en/password/reset|/fr/mot-de-passe/reinitialisation|/de/passwort/zurücksetzen), roles: IS_AUTHENTICATED_ANONYMOUSLY}
# Allow anonymous to visit email_send_password_forgot
- { path: ^(/en/email/send/password/forgot|/fr/courriel/envoyer/mot-de-passe|/de/email/schreiben/passwort/vergessen), roles: IS_AUTHENTICATED_ANONYMOUSLY}
# Allow only admin to visit admin url
- { path: ^/admin, roles: IS_ADMIN}
# Allow authenticated user ONLY to visit every other urls
# Specific user right controls are managed inside controller
- { path: ^/, roles: IS_AUTHENTICATED_FULLY}
正如我所说,这是可行的,但我必须为每条现有路线复制路径。
我让你看看路线以便更好地理解:
> php bin/console debug:router
Name Method Scheme Host Path
-------------------------------- -------- -------- ------ --------------------
password_reset.en ANY ANY ANY /{_locale}/password/reset/{user_id}/{token_value}
password_reset.fr ANY ANY ANY /{_locale}/mot-de-passe/reinitialisation/{user_id}/{token_value}
password_reset.de ANY ANY ANY /{_locale}/passwort/zurücksetzen/{user_id}/{token_value}
login.en ANY ANY ANY /{_locale}/login
login.fr ANY ANY ANY /{_locale}/connexion
login.de ANY ANY ANY /{_locale}/verbindung
logout ANY ANY ANY /{_locale}/logout
index_no_locale ANY ANY ANY /
...
我真的不喜欢这个,因为每次必须添加或修改 URL 时都会对 opeer 进行冗余修改。
主要问题是当用户未登录并访问需要 IS_AUTHENTICATED_FULLY
角色的 URL 时。
所以现在 'Voter' 表示访问被拒绝并将响应重定向到 login_path 定义为 security.yaml
问题来了。我无法定义 login_path 的正确路径,因为我无法猜测用户使用的语言环境是什么。所以我对此进行了硬编码:
# ./config/packages/security.yaml @ line 1 -- 21
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
...
firewalls:
dev:
...
main:
anonymous: true
form_login:
login_path: /en/login
check_path: /en/login
provider: my_provider
logout:
path: /en/logout
guard:
...
实际上注销也一样...
据此https://symfony.com/doc/current/security.html#logging-out
您可以让 security.firewalls.main.logout.path
引用路由名称。至于登录,您也可以参考路由名称,但推荐的方法是使用 guard authenticators 参见 https://symfony.com/doc/current/security/form_login.html.
编辑:
至于 access_control
,当我查看 Symfony\Component\HttpFoundation\RequestMatcher
中的代码时,它不会查找路由名称。所以我看到了两个选项。
- 你找到了一种方法来创建你自己的 RequestMatcher 并让 Symfony 使用它,在我看来,这对于你需要的东西来说似乎过于复杂了。
- 为您现在正在做的
access_control
中的每个语言环境创建一个条目。为了更好的可读性,我通常会把每个条目放在自己的行上,而不是像你那样使用正则表达式or
,但我就是这样。