Как работать с областями действия ROLES и FOSOAuthServerBundle

У меня есть базовый API, который аутентифицирует пользователей с помощью FOSOAuthServerBundle. Пользователи могут иметь роли ROLE_USER и ROLE_ADMIN. Основываясь на документах FOSOAuthServerBundle, поведение по умолчанию - использовать области в качестве ролей, поэтому я подумал, что, когда у меня есть обычный пользователь, пакет будет возвращать scope: user в ответе, а когда это пользователь-администратор, вернет scope: admin. Но так не работает. Пакет возвращает все, что настроено в supported_scopesentry. Ниже мой config.yml.

fos_oauth_server:
    service:
        options:
            supported_scopes: user admin

Мой access_control раздел в security.yml пуст, а мой firewalls раздел ниже:

firewalls:
        users_create:
            pattern: ^/v1/users
            methods: [POST]
            security: false

        api:
            pattern:    ^/
            security: true
            fos_oauth:  true
            stateless:  true

access_control:
        # You can omit this if /api can be accessed both authenticated and anonymously

Таким образом, пакет всегда возвращает user admin в качестве области видимости, даже если у пользователя нет роли ROLE_ADMIN.

{
"access_token": "ZGQ2ODE5ZjAzNTZkOWY0OWMyNmZmODE4MjcwZTJmYjExNzY0NzQxOTRmMzk4NzA2Mjc2NjIyZmY1ZDgwMzk4NA"
"expires_in": 3600
"token_type": "bearer"
"scope": "user admin"
"refresh_token": "NmM5ZGFmNzBiNTNjYmQzMTQ1MTk0ODJjOTAxMWU0YWIwMzM1MzgyODg4ZTAzNTI5ZTk2MDc3OGU2MTg0MWZiMA"
}

Что мне не хватает? Разве роль пользователя не привязана к области токена? Есть ли лучший способ узнать, является ли мой пользователь администратором или нет?


person Hugo Nogueira    schedule 13.01.2016    source источник
comment
Может это не ваш security.yml а это паста от config.yml? Не могли бы вы предоставить access_control: раздел от себя security.yml?   -  person Ilya Yarkovets    schedule 28.01.2016
comment
Ты прав Илья. Редактирую свой вопрос.   -  person Hugo Nogueira    schedule 28.01.2016


Ответы (4)


Из документа поведение по умолчанию - отображение объемы с ролями. В вашем случае это будут роли ROLE_USER и ROLE_ADMIN.

Теперь, чтобы ограничить использование, вы должны отредактировать файл security.yml примерно так:

# app/config/security.yml
security:
    access_control:
        - { path: ^/api/super/secured, role: ROLE_ADMIN }
        - { path: ^/api/general, role: ROLE_USER }

Чтобы ограничить доступ к контроллеру, вы можете использовать это:

if ($this->get('security.context')->isGranted('ROLE_ADMIN')) {
    // the user has the ROLE_ADMIN role, so act accordingly
}

Снова из документа,

Теперь клиенты смогут передавать параметр области при запросе токена доступа.

Надеюсь это поможет.

ОБНОВЛЕНИЕ:

Посмотрите этот ответ здесь на аналогичный вопрос и это статья о настройке FOSOAuthServerBundle. Обратите особое внимание на конфигурационную часть.

person steady_daddy    schedule 02.02.2016
comment
Но как я могу узнать в моем интерфейсе, является ли мой пользователь администратором или нет? - person Hugo Nogueira; 03.02.2016
comment
В шаблоне Twig вы можете сделать это: {% if is_granted('ROLE_ADMIN') %} {# Some text #} {% endif %} Или реализовать метод isGranted в своей сущности User (stackoverflow.com/questions/9080530/) - person Delphine; 03.02.2016
comment
Дельфина, вы меня не поняли. Я использую REST Api и запрашиваю данные из своего интерфейса javascript. Мне нужно сделать запрос API, а затем узнать мою роль пользователя. Эти данные не приходят, когда я делаю запрос. Когда мы запрашиваем токен API, возврат (как упоминалось выше) приходит с параметром области действия. Но я не знаю, правильно ли это, и похоже, что это не работает. - person Hugo Nogueira; 04.02.2016
comment
@hugomn Как вы используете API? - person steady_daddy; 04.02.2016
comment
Я запрашиваю токен доступа при входе в систему, а затем использую токен доступа во всех последующих запросах. После получения токена мне нужно знать, является ли пользователь администратором или нет. - person Hugo Nogueira; 04.02.2016

FOSOAuthServerBundle аутентифицируйте своего пользователя на основе токена, поэтому вам не нужно беспокоиться об объемах, это другое дело, чем роли. Внутри вашего контроллера вы можете получить $this->getUser(), чтобы получить текущего аутентифицированного пользователя. Если это работает, проверьте, работает ли isGranted.

http://symfony.com/doc/current/book/security.html

public function helloAction($name)
{
    // The second parameter is used to specify on what object the role is tested.
    $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');

    // Old way :
    // if (false === $this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
    //     throw $this->createAccessDeniedException('Unable to access this page!');
    // }

    // ...
}

В случае, если $this->getUser() не работает, вам нужно установить fetch на EAGER на объекте AccessToken.

class AccessToken extends BaseAccessToken
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Client")
     * @ORM\JoinColumn(nullable=false)
     */
    protected $client;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", fetch="EAGER")
     */
    protected $user;
}
person vardius    schedule 03.02.2016
comment
Вы не поняли мою точку зрения. Мне нужен способ узнать, какова роль пользователя в моем интерфейсе. Итак, когда я запрашиваю токен, мне также нужно знать, в каких ролях был предоставлен пользователь. У нас уже есть параметр «scope» в токене, но похоже, что он работает не так, как ожидалось (я привел пример выше). - person Hugo Nogueira; 03.02.2016
comment
нельзя просто получить текущие пользовательские данные из api? - person vardius; 03.02.2016
comment
Нет ... при запросе сведений о пользователе FOSOAuthServerBundle не возвращает области или правила. Если вы обратите внимание на мой вопрос, вы увидите, что запрос / token дает вам возможности, но он не работает, как ожидалось. - person Hugo Nogueira; 04.02.2016
comment
я имею в виду с другим запросом, создайте действие, в котором вы возвращаете пользователя по токену - person vardius; 04.02.2016
comment
Но когда я возвращаю объект пользователя, он не имеет информации о ролях пользователя. Кроме того, мне нужно понять, для чего используется параметр scopes в ответе на токен. - person Hugo Nogueira; 04.02.2016

На github есть проблема, которая датируется 2013 годом для этого. Если вы прочитаете этот выпуск и перейдете по ссылкам, в конечном итоге вы увидите, что пользователь Spomky создает свою собственную библиотеку и пакет Symfony и предлагается в качестве сопровождающего FOSAuthServerBundle. Похоже, что организация FOS объединит работу Spomky в следующую основную версию FOSOAuthServerBundle, как только она станет стабильной.

person bblue    schedule 17.03.2016

Вы можете вернуть информацию об учетной записи пользователя вместе с токеном.

Вот мой подход к подобной ситуации: я создал прокси-маршрут, который принимает имя пользователя и пароль в качестве параметров запроса, добавляет информацию о клиенте oauth в запрос и перенаправляет запрос в действие с токеном Oauth. Затем я беру эту информацию и возвращаю информацию о пользователе вместе с токеном.

/**
 * @REST\Post("/authorize")
 */
public function loginAction(Request $request){
    $request->request->add( array(
        'grant_type' => 'password',
        'client_id' => $this->container->getParameter('oauth_client_id') . "_" . $this->container->getParameter('oauth_client_random_id'),
        'client_secret' => $this->container->getParameter('oauth_client_secret')
    ));
    $tokenAction = $this->get('fos_oauth_server.controller.token')->tokenAction($request);
    $tokenObject = json_decode( $tokenAction->getContent() );

    if(key_exists('error_description', $tokenObject)){
        return $this->view(["error" => $tokenObject->error_description], 401);
    };


    $user = $this->getDoctrine()->getRepository('\App\Entity\Oauth\AccessToken')->findOneBy( array('token' => $tokenObject->access_token ) )->getUser();
    $return = array(
        "roles" => $user->getUser()->getRoles(),
        "access_token" => $tokenObject->access_token,
        "expires_in" => $tokenObject->expires_in,
        "token_type" => $tokenObject->token_type,
        "scope" =>$tokenObject->scope,
        "refresh_token" => $tokenObject->refresh_token
    );
    return $this->view($return);
}

Я использую этот маршрут для аутентификации / генерации токенов, а не использую маршрут, который поставляется с OAuthBundle.

person Shawn Northrop    schedule 14.05.2018