更改后重新加载用户角色,无需重新登录 [英] Reload user role after change without re-logging

查看:22
本文介绍了更改后重新加载用户角色,无需重新登录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何刷新登录的用户角色,例如什么时候被管理员用户改变了?我找到了 always_authenticate_before_granting 安全选项(它不包含在 Symfony 4 文档中)并将其设置为 true.

How to refresh logged in user role e.g. when it has been changed by admin user? I've found the always_authenticate_before_granting security option (it's not included in Symfony 4 documentation) and set it to true.

security.yaml:

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 订阅者:

I've created onRequest subscriber:

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 中 >Security Token 列出的是旧的(当然,如果我没有设置新的令牌).

and now I can refresh the updated roles on every request, but comparing sessionUser to databaseUser is pointless, because the sessionUser always contains newly updated roles, though in Symfony Profiler > Security Token are listed the old ones (in case when I don't set the new token, of course).

推荐答案

Tl;dr 恐怕您将不得不引入自己的机制才能使这项工作发挥作用.

Tl;dr I'm afraid you will have to introduce a mechanism of your own in order to make this work.

会话令牌存储在用户的会话中.这将对您的应用程序的性能产生相当大的影响,因为每次都需要调用数据库以检查角色是否已更改.

The session token is stored inside the user's session. This will have quite an impact on your application's performance, because each time a call to the database will be required in order to check if the role had changed.

所以你需要一个请求监听器这会将数据库角色与当前用户角色进行比较,如果不同,则替换会话中的令牌,这次使用新的角色列表,例如.(伪代码):

So you will need a request listener which will compare database role with current user role, and if it is not same, replace the token in the session, this time with new role list, eg. (pseudo code):

sessionUser = tokenStorage.token.user
databaseUser = userRepository.find(sessionUser.id)

if sessionUser.roles !== databaseUser.roles
    tokenStorage.setToken(new PostAuthenticationGuardToken(…))

或使用缓存作为标志载体来通知用户有关更改.这种方法肯定会快得多.

or use a cache as a flag carrier to notify the user about the change. This method is going to be much quicker for sure.

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)

无论哪种方式,用户都必须询问应用程序是否对每个请求进行了角色更改.

Either way the user has to ask the application has there been role change, on each request.

这篇关于更改后重新加载用户角色,无需重新登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆