【问题标题】:How to deal with ROLES and FOSOAuthServerBundle scopes如何处理 ROLES 和 FOSOAuthServerBundle 范围
【发布时间】:2016-01-13 18:02:36
【问题描述】:

我有一个使用 FOSOAuthServerBundle 对用户进行身份验证的基本 api。用户可以具有 ROLE_USER 和 ROLE_ADMIN 角色。基于 FOSOAuthServerBundle 文档,默认行为是使用作用域作为角色,所以我认为当我有普通用户时,捆绑包会在响应中返回 scope: user,当它是管理员用户时,会返回 @987654322 @。但它不是这样工作的。捆绑包返回supported_scopesentry 中配置的任何内容。下面是我的config.yml

fos_oauth_server:
    service:
        options:
            supported_scopes: user admin

security.yml 中我的access_control 部分为空,而我的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

这样,即使用户没有 ROLE_ADMIN 角色,捆绑包总是返回 user admin 作为范围。

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

我错过了什么?用户角色不是附加到令牌范围吗?有没有更好的方法来知道我的用户是否是管理员?

【问题讨论】:

  • 可能不是你的security.yml 而是从config.yml 粘贴的?您能提供access_control: 部分的security.yml 吗?
  • 你说得对,伊莉雅。编辑我的问题。

标签: php symfony oauth fosoauthserverbundle


【解决方案1】:

doc 开始,默认行为是映射作用域和角色。在您的情况下,角色将是 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
}

再次来自doc

现在,客户端可以在请求时传递范围参数 访问令牌。

希望这会有所帮助。

更新:

查看here 对类似问题的回答和article 设置 FOSOAuthServerBundle 。密切关注配置部分。

【讨论】:

  • 但是我如何在前端知道我的用户是否是管理员?
  • 在 Twig 模板中你可以这样做:{% if is_granted('ROLE_ADMIN') %} {# Some text #} {% endif %} 或者在你的用户实体中实现一个 isGranted 方法(stackoverflow.com/questions/9080530/…
  • 德尔芬,你没明白我的意思。我使用 REST Api 并从我的 javascript 前端请求数据。我需要做一个 API 请求,然后获取我的用户角色。当我做 /me 请求时,这些数据不会出现。当我们请求 API 令牌时,返回(如上所述)带有一个“范围”参数。但我不知道这是否是正确的方法,并且看起来它不起作用。
  • @hugomn 你是如何使用 API 的?
  • 我在登录时请求访问令牌,然后在所有后续请求中使用访问令牌。获得令牌后,我需要知道用户是否是管理员。
【解决方案2】:

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() 不起作用,您必须在AccessToken 实体上将fetch 设置为EAGER

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;
}

【讨论】:

  • 你没有明白我的意思。我需要一种方法来了解用户在我的前端中的角色。因此,当我请求令牌时,我还需要知道已授予用户哪些角色。我们在令牌中已经有了“范围”参数,但看起来它没有按预期工作(我在上面放了一个例子)。
  • 不能直接从api获取当前用户数据吗?
  • 否...当您请求用户详细信息时,FOSOAuthServerBundle 不会返回范围或规则。如果您注意我的问题,您会看到 /token 请求为您提供了范围,但它没有按预期工作。
  • 我的意思是用不同的请求,创建一个你通过令牌返回用户的操作
  • 但是当我返回一个用户对象时,它没有关于用户角色的信息。另外,我需要了解用于令牌响应中的“范围”参数是什么。
【解决方案3】:

github 上有一个问题,日期为back to 2013 for this。如果您阅读了该问题并点击链接,您最终会看到用户 Spomky 创建 his own library and Symfony bundle 并成为 FOSAuthServerBundle 的 suggested as a maintainer。看来 FOS 组织将在 Spomky 的工作稳定后将其合并到 FOSOAuthServerBundle 的下一个主要版本中。

【讨论】:

    【解决方案4】:

    您可以将用户帐户信息与令牌一起返回。

    这是我处理类似情况的方法,我创建了一个代理路由,它将用户名和密码作为请求参数,将 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 附带的路由

    【讨论】:

      猜你喜欢
      • 2017-05-18
      • 1970-01-01
      • 2019-07-08
      • 1970-01-01
      • 2018-01-09
      • 2014-05-17
      • 2016-04-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多