具有相同模式的多个防火墙

问题描述 投票:0回答:2

我目前有以下配置, 从外部消费者发送令牌时,端点/api 工作正常。

但我现在想重用这个模式^/api,在使用会话的应用程序中使用ajax。如何配置防火墙以无状态或会话方式为我工作?

security:
    encoders:
        FOS\UserBundle\Model\UserInterface: bcrypt
        App\Entity\User\User:
            algorithm: bcrypt

    role_hierarchy:
        ROLE_ADMIN: [ROLE_USER, ROLE_ALLOWED_TO_SWITCH]
        ROLE_SUPER_ADMIN: ROLE_ADMIN

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username_email
        app_user_provider:
            entity:
                class: App\Entity\User\User
                property: username

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        logout:
            pattern: ^/api/logout
            stateless: true
            anonymous: true
            logout:
                path:  app_logout
                success_handler: "app.webservice_logout_success_listener"
        api:
            pattern: ^/api
            stateless: true
            anonymous: true
            provider: app_user_provider
            json_login:
                check_path: /api/login_check
                username_path: username
                password_path: password
                success_handler: lexik_jwt_authentication.handler.authentication_success
                failure_handler: lexik_jwt_authentication.handler.authentication_failure
            guard:
                authenticators:
                    - lexik_jwt_authentication.jwt_token_authenticator
        admin:
            context: user
            switch_user: true
            pattern:  ^/
            anonymous: ~
            provider: fos_userbundle
            form_login:
                login_path: admin_login
                check_path: admin_login
                default_target_path: easyadmin
                failure_path: admin_login
            logout:
                path:   /logout
                target: /login

symfony api-platform.com lexikjwtauthbundle
2个回答
0
投票

我找到了解决方案,很抱歉花时间回复。 我不知道该解决方案是否是最好的方法,但我想了解有关其他可能实现的意见。

一方面,我启用Lexik,以获取cookie的令牌。

# config/packages/lexik_jwt_authentication.yaml
lexik_jwt_authentication:
    # some_config:
    token_extractors:
        # check token in a cookie
        cookie:
            enabled: true
            name:    Bearer

另一方面,当用户通过会话进行身份验证时,我会重写该函数,设置 cookie 并使用 Lexik 以编程方式生成令牌

<?php

namespace App\Security;

use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler as BaseDefaultAuthenticationSuccessHandler;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Http\HttpUtils;

class DefaultAuthenticationSuccessHandler extends BaseDefaultAuthenticationSuccessHandler
{

    private $JWTManager;

    public function __construct(
        JWTTokenManagerInterface $JWTManager,
        HttpUtils $httpUtils,
        array $options = []
    )
    {
        parent::__construct($httpUtils, $options);
        $this->JWTManager = $JWTManager;
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token)
    {
        /** @var Response $response */
        $response = parent::onAuthenticationSuccess($request, $token);
        $response->headers->setCookie(Cookie::create('Bearer', $this->JWTManager->create($token->getUser())));
        return $response;
    }
}

0
投票
# config/packages/lexik_jwt_authentication.yaml
lexik_jwt_authentication:
    # some_config:
    token_extractors:
        # check token in a cookie
        cookie:
            enabled: true
            name:    Bearer

/**
 * in order /api requests work out of box in main firewall
 * we can inject jwt token to cookie and refresh it near expiration time
 */
readonly class IntegrateJWTToCookieForMainFirewall
{
    public function __construct(
        private Security $security,
        private JWTTokenManagerInterface $JWTManager,
    ) {
    }

    public function __invoke(ResponseEvent $event): void
    {
        $request = $event->getRequest();
        $firewallConfig = $this->security->getFirewallConfig($request);
        $firewallName = $firewallConfig?->getName();

        if ($firewallName === 'main' && ($user = $this->security->getUser())) {
            $response = $event->getResponse();
            $token = $request->cookies->get('Bearer');

            $shouldRefreshToken = false;
            if ($token) {
                try {
                    $payload = $this->JWTManager->parse($token);
                    $tokenExpiry = DateTimeImmutable::createFromFormat('U', (string)$payload['exp']);

                    $shouldRefreshToken = $tokenExpiry <= (new DateTimeImmutable())->modify('+ 15 min');
                } catch (JWTDecodeFailureException $e) {
                    $shouldRefreshToken = true;
                }
            }

            if (!$token || $shouldRefreshToken) {
                $newToken = $this->JWTManager->create($user);
                $response->headers->setCookie(Cookie::create('Bearer', $newToken));
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.