isGranted 为登录的用户 JWT 返回 false - Symfony API-Platform AWS-EB

Posted

技术标签:

【中文标题】isGranted 为登录的用户 JWT 返回 false - Symfony API-Platform AWS-EB【英文标题】:isGranted returns false for logged in user JWT - Symfony API-Platform AWS-EB 【发布时间】:2020-06-26 04:10:33 【问题描述】:

我已经使用 JWT 令牌向 ElasticBeanstalk 部署了一个 API-Platform 应用程序,它像往常一样在我的本地服务器上运行良好。

在 EB 上,尽管提供了正确的 BearerToken,但它拒绝访问已登录的用户。

这是抛出的错误:


 "errors": [
    
        "message": "Access Denied.",
        "extensions": 
            "category": "graphql"
        ,
        "locations": [
            
                "line": 6,
                "column": 9
            
        ],
        "path": [
            "retrievedQueryUser"
        ]
    
],
"data": 
    "retrievedQueryUser": null


有问题的查询尝试通过以下graphql 配置检索用户配置文件信息:

*          "retrievedQuery"=
*              "item_query"=UserProfileResolver::class,
*              "normalization_context"="groups"="get-owner",
*              "security"="is_granted('IS_AUTHENTICATED_FULLY') and object == user"
*          ,

因此,检查用户是否为IS_AUTHENTICATED_FULLY 以及是否是他/她自己尝试执行查询应该是一件简单的事情。

据我所知,通过下面的 /vendor/symfony/security-core/Authorization/AuthorizationChecker.php 转储,它未能检索到令牌。

 var_dump($this->tokenStorage->getToken()->getUser()->getUsername());

我粗略地比较了我的本地安装和 AWS-EB 上的 phpinfo(),但没有发现任何明显的不匹配。

这是/config/packages/lexik_jwt_authentication.yaml 的 JWT 配置。

lexik_jwt_authentication:
   secret_key: '%env(resolve:JWT_SECRET_KEY)%'
   public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
   pass_phrase: '%env(JWT_PASSPHRASE)%'
   user_identity_field: email
   token_ttl: 1800

只是为了确认用户能够登录。它通过了失败的isGranted() 检查。

有什么想法吗?

编辑 - 添加`/config/packages/security.yaml

security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
encoders:
    App\Entity\User:
        algorithm: auto
        #algorithm: bcrypt
        #algorithm: argon2i
        cost: 12
providers:
    database:
        entity:
            class: App\Entity\User
            property: email
firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    refresh:
        pattern:  ^/api/token/refresh
        stateless: true
        anonymous: true
    api:
        pattern:  ^/api
        stateless: true
        anonymous: true
        json_login:
            check_path:               /api/login_check
            success_handler:          lexik_jwt_authentication.handler.authentication_success
            failure_handler:          lexik_jwt_authentication.handler.authentication_failure
        guard: 
            authenticators: 
                - app.google_login_authenticator
                - App\Security\TokenAuthenticator
            entry_point: App\Security\TokenAuthenticator
        user_checker: App\Security\UserEnabledChecker
     access_control:
    -  path: ^/login,     roles: IS_AUTHENTICATED_ANONYMOUSLY 
    -  path: ^/admin,     roles: ROLE_SUPERADMIN 
    -  path: ^/api/token/refresh, roles: IS_AUTHENTICATED_ANONYMOUSLY 
    -  path: ^/api,       roles: IS_AUTHENTICATED_ANONYMOUSLY 
role_hierarchy:
    ROLE_PROVIDER: ROLE_USER
    ROLE_ADMIN: [ROLE_PROVIDER, ROLE_EDITOR]
    ROLE_SUPERADMIN: ROLE_ADMIN

【问题讨论】:

路由和防火墙配置是什么?其他需要 JWT 令牌的受保护路径是否有效? 我在问题正文中添加了security.yaml。关于路线,这是graphql,它们都看起来像:https:mywebsite/api/graphql 根据您的访问控制规则,/api/graphql 不需要身份验证。 /api/graphql 上的其他路由是否需要身份验证工作?我会将IS_AUTHENTICATED 规则移到您的访问控制部分,并在安全注释上添加object == user 没错:/api/graphql 不需要身份验证。有几个查询对任何人开放。但是为了获取大部分用户信息,访问控制在查询级别就位,并且,在有问题的查询的情况下,用户都应该经过身份验证,并且应该是他/她自己来访问信息的用户.总的来说,我认为这与安全配置无关。如前所述,使用相同的配置在本地一切正常。 【参考方案1】:

经过进一步研究,我发现 Apache 正在从请求中剥离授权令牌。

/lexik/jwt-authenticator-bundle/Security/Guard/JWTTokenAuthenticator 的方法supports 上,如下转储将不包含AWS 上的令牌:

 var_dump($request->headers->all());
 var_dump($_SERVER);

根据this question,这是不接受授权标头的 Apache 配置问题。

指示的解决方案是将以下内容添加到.htaccess

 SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

这解决了这个问题,但应该注意,如果没有对 .htaccess 进行上述编辑,本地 Apache 安装工作正常。

所以,也应该可以直接更改 Apache 配置,但我找不到如何去做。

编辑:后来我在“JWT-Token”文档上找到了如下的特定说明,确认了this link 上的解决方案。

【讨论】:

以上是关于isGranted 为登录的用户 JWT 返回 false - Symfony API-Platform AWS-EB的主要内容,如果未能解决你的问题,请参考以下文章

Flask JWT 令牌/有效负载 - 返回用户 Json

基于jwt的用户登录认证

Sonata Admin:isGranted() 在 Admin 类中总是返回 true,但在模板中返回正确的布尔值

Symfony2 中 isGranted 的替代方案

用户登录鉴权JWT代码实现

用户登录鉴权JWT代码实现