如何刷新登录的用户角色,例如管理员用户何时更改过?我找到了always_authenticate_before_granting
安全选项(Symfony 4文档中未包含)并将其设置为true
。
security.yaml:
security:
always_authenticate_before_granting: true
encoders:
App\Entity\Main\User:
algorithm: bcrypt
providers:
app_user_provider:
entity:
class: App\Entity\Main\User
property: email
role_hierarchy:
ROLE_ADMIN: ROLE_USER
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
guard:
authenticators:
- App\Security\LoginFormAuthenticator
form_login:
login_path: login
check_path: login
logout:
path: logout
target: homepage
remember_me:
secret: '%kernel.secret%'
path: /
access_control:
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/.*, roles: ROLE_USER }
但没有生效。
我已经创建了onRequest订户:
class RequestSubscriber implements EventSubscriberInterface
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => 'onRequest'
];
}
public function onRequest(GetResponseEvent $event): void
{
if (!$event->isMasterRequest()) {
return;
}
if(!$token = $this->tokenStorage->getToken()) return;
$sessionUser = $token->getUser();
if ($sessionUser instanceof User) {
$this->tokenStorage->setToken(new PostAuthenticationGuardToken($sessionUser, 'main', $sessionUser->getRoles()));
}
}
}
现在我可以在每个请求上刷新更新的角色,但是将sessionUser与databaseUser进行比较是没有意义的,因为sessionUser始终包含新更新的角色,尽管在Symfony Profiler>安全令牌中列出了旧角色(以防万一,当然,不要设置新令牌。
答案 0 :(得分:1)
Tl; dr恐怕您必须引入自己的机制才能使这项工作生效。
会话令牌存储在用户会话中。这将对您的应用程序的性能产生很大的影响,因为每次都需要调用数据库以检查角色是否已更改。
因此,您将需要一个request listener,它将数据库角色与当前用户角色进行比较,如果不相同,则用新的角色列表替换会话中的令牌,例如。 (伪代码):
sessionUser = tokenStorage.token.user
databaseUser = userRepository.find(sessionUser.id)
if sessionUser.roles !== databaseUser.roles
tokenStorage.setToken(new PostAuthenticationGuardToken(…))
或将高速缓存用作标志载体,以将更改通知用户。当然,这种方法会更快。
sessionUser = tokenStorage.token.user
// of course the flag has to be set when the user's role gets changed
cacheToken = 'users.role_reload.' . sessionUser.id
if cache.has(cacheToken)
databaseUser = userRepository.find(sessionUser.id)
tokenStorage.setToken(new PostAuthenticationGuardToken(…))
cache.remove(cacheToken)
无论哪种方式,用户都必须在每次请求时要求应用程序进行角色更改。