【问题标题】:Symfony 4 API Platform+LexikJWTAuthenticationBundle : Bad credentialsSymfony 4 API Platform+LexikJWTAuthenticationBundle:错误的凭据
【发布时间】:2019-05-24 21:41:20
【问题描述】:

我正在尝试使用 LexikJWTAuthenticationBundle 创建 JWT 身份验证。

http://127.0.0.1:8000/api/http://127.0.0.1:8000/api/login_check?username=****&password=**** 我都明白了

{
  "code": 401,
  "message": "Bad credentials"
}

作为回应。

我的 security.yaml 如下所示:

security:
    encoders:
        FOS\UserBundle\Model\UserInterface: sha512

    App\Entity\User:
        algorithm: bcrypt

providers:
    my_provider:
        entity:
            class: App\Entity\User
            property: username           


firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false

    login:
        pattern:  ^/backend/api/login
        stateless: true

        form_login:
            check_path:               /backend/api/login_check
            username_parameter:       _username
            password_parameter:       _password
            success_handler:          lexik_jwt_authentication.handler.authentication_success
            failure_handler:          lexik_jwt_authentication.handler.authentication_failure
            require_previous_session: false
        guard:
            authenticators:
                - App\Security\LoginFormAuthenticator
    api:
        pattern:   ^/api
        stateless: true
        lexik_jwt: ~

        guard:
                authenticators:
                    - lexik_jwt_authentication.jwt_token_authenticator
  access_control:
        - { path: ^/api/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api,       roles: IS_AUTHENTICATED_FULLY }

routes.yaml 是:

api_login_check:
    path:     api/login_check

lexik_jwt_authentication.yaml

lexik_jwt_authentication:
    secret_key:       '%kernel.project_dir%/config/jwt/private.pem' # required for token creation
    public_key:       '%kernel.project_dir%/config/jwt/public.pem'  # required for token verification
    pass_phrase:      'pass' # required for token creation, usage of an environment variable is recommended
    token_ttl:        86400

Entity/User.php 文件:

<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * @ApiResource()
 * @ORM\Table(name="user")
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 */
class User implements UserInterface, \Serializable
{
/**
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $id;

/**
 * @ORM\Column(type="string", length=255)
 */
private $username;

/**
 * @ORM\Column(type="string", length=255)
 */
private $fullname;

/**
 * @ORM\Column(type="string", length=255)
 */
private $password;

/**
 * @ORM\Column(type="string", length=255)
 */
private $email;

/**
 * @ORM\Column(type="string", length=255, nullable=true)
 */
private $mobile;

/**
 * @ORM\Column(type="string", length=255, nullable=true)
 */
private $bild;

/**
 * @ORM\Column(type="boolean")
 */
private $status;

/**
 * @ORM\Column(type="integer")
 */
private $usergroupid;

/**
 * @ORM\Column(type="string", length=255, nullable=true)
 */
private $activewidgetid;

public function getId(): ?int
{
    return $this->id;
}

public function getUsername(): ?string
{
    return $this->username;
}

public function setUsername(string $username): self
{
    $this->username = $username;

    return $this;
}

public function getFullname(): ?string
{
    return $this->fullname;
}

public function setFullname(string $fullname): self
{
    $this->fullname = $fullname;

    return $this;
}

public function getPassword(): ?string
{
    return $this->password;
}

public function setPassword(string $password): self
{
    $this->password = $password;

    return $this;
}

public function getEmail(): ?string
{
    return $this->email;
}

public function setEmail(string $email): self
{
    $this->email = $email;

    return $this;
}

public function getMobile(): ?string
{
    return $this->mobile;
}

public function setMobile(?string $mobile): self
{
    $this->mobile = $mobile;

    return $this;
}

public function getBild(): ?string
{
    return $this->bild;
}

public function setBild(?string $bild): self
{
    $this->bild = $bild;

    return $this;
}

public function getStatus(): ?bool
{
    return $this->status;
}

public function setStatus(bool $status): self
{
    $this->status = $status;

    return $this;
}

public function setEnabled(bool $enabled): self
{
    $this->enabled = $enabled;

    return $this;
}

public function setSuperAdmin(bool $enabled): self
{
    $this->enabled = $enabled;

    return $this;
}

public function getUsergroupid(): ?int
{
    return $this->usergroupid;
}

public function setUsergroupid(int $usergroupid): self
{
    $this->usergroupid = $usergroupid;

    return $this;
}

public function getActivewidgetid(): ?string
{
    return $this->activewidgetid;
}

public function setActivewidgetid(?string $activewidgetid): self
{
    $this->activewidgetid = $activewidgetid;

    return $this;
}
public function getRoles()
{
    return array('ROLE_ADMIN');
}
public function getSalt() {}

public function eraseCredentials() {}

public function serialize()
    {
        return serialize([
            $this->id,
            $this->username,
            $this->password,
            $this->email
        ]);
    }

public function unserialize($string)
    {
        list (
            $this->id,
            $this->username,
            $this->password,
            $this->email             
        ) = unserialize($string, ['allowed_classes' => false]);
        }
}

我什至无法访问 Swagger,我的 api_platfrom.yaml 看起来像:

# api/config/packages/api_platform.yaml
api_platform:
    swagger:
         api_keys:
             apiKey:
                name: Authorization
                type: header

键也被创建:

任何建议,解决方案?提前致谢

【问题讨论】:

标签: php jwt symfony4 api-platform.com


【解决方案1】:

我认为a更进一步。

我将 security.yaml 更改为:

security:
    encoders:
        App\Entity\User:
            algorithm: bcrypt
providers:
    entity_provider:
        entity:
            class: App\Entity\User
            property: username

firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    login:
        pattern:  ^/login
        stateless: true
        anonymous: true
        json_login:
            check_path: /login_check
            success_handler: lexik_jwt_authentication.handler.authentication_success
            failure_handler: lexik_jwt_authentication.handler.authentication_failure

    register:
        pattern:  ^/register
        stateless: true
        anonymous: true

    api:
        pattern:  ^/api
        stateless: true
        anonymous: false
        provider: entity_provider
        guard:
            authenticators:
                - lexik_jwt_authentication.jwt_token_authenticator

access_control:
    - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/api/, roles: IS_AUTHENTICATED_FULLY }

现在我对http://localhost:8000/api//api/login_check 的回复是

{
  "code": 401,
  "message": "JWT Token not found"
}

即使我尝试使用 CURL,我也会得到相同的响应:

/api 锁定在 LexikJTW 捆绑包之前,如下所示:https://demo.api-platform.com

如何带回 api plafrom 并获取令牌作为响应? 我的想法和选择都快用完了...

【讨论】:

    【解决方案2】:

    我解决了。 我在 security.yml 中所做的更改:

    security:
        encoders:
    
        App\Entity\User:
            algorithm: bcrypt
    
    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: ROLE_ADMIN
    
    providers:
        entity_provider:
            entity:
                class: App\Entity\User
                property: username
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        login:
            pattern:  ^/login
            stateless: true
            anonymous: true
            form_login:
                check_path: api_login_check
                login_path: api_login_check
                success_handler: lexik_jwt_authentication.handler.authentication_success
                failure_handler: lexik_jwt_authentication.handler.authentication_failure
                require_previous_session: false
                username_parameter: username
                password_parameter: password
    
        api:
            pattern:   ^/api
            stateless: true
            provider: entity_provider
            guard:
                authenticators:
                    - lexik_jwt_authentication.jwt_token_authenticator
    
    access_control:
        - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/api/, roles: IS_AUTHENTICATED_FULLY}
    

    现在在localhost:8000/login_check 我可以获得令牌:

    之后,当我尝试访问 localhost:8000/api(例如,使用 curl -H "Authorization: Bearer [TOKEN]" http://localhost:8000/api)时,我收到错误响应:

    {
        "code": 401,
        "message": "Unable to find key \"username\" in the token payload."
    }
    

    但这是另一种情况。我会将其标记为已解决。希望它会对某人有所帮助。

    【讨论】:

      【解决方案3】:

      这是一个适用于我的示例,使用 FOSUserBundle :

      security.yaml

      security:
          encoders:
              FOS\UserBundle\Model\UserInterface: bcrypt
          providers:
              fos_userbundle:
                  id: fos_user.user_provider.username
      
          firewalls:
              dev:
                  pattern: ^/_(profiler|wdt)
                  security: false
              api:
                  pattern:   ^/api/users              # protected path
                  stateless: true
                  guard:
                      authenticators:
                          - lexik_jwt_authentication.jwt_token_authenticator
              main:
                  stateless: true
                  anonymous: true
                  provider: fos_userbundle
                  json_login:
                      check_path: /authentication_token
                      username_path: username
                      password_path: password
                      success_handler: lexik_jwt_authentication.handler.authentication_success
                      failure_handler: lexik_jwt_authentication.handler.authentication_failure
      
          access_control:
              - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
              - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
              - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
              - { path: ^/admin/, role: ROLE_ADMIN }
      

      api_plateform.yaml

      api_platform:
          mapping:
              paths: ['%kernel.project_dir%/src/Entity']
          # enable_fos_user: true
          swagger:
               api_keys:
                   apiKey:
                      name: Authorization
                      type: header
      

      routing.yaml

      # app/config/routing.yml
      fos_user:
          resource: "@FOSUserBundle/Resources/config/routing/all.xml"
      
      authentication_token:
          path: /authentication_token
          methods: ['POST']
      

      lexik_jwt_authentication.yaml

      lexik_jwt_authentication:
          secret_key:       '%kernel.project_dir%/config/jwt/private.pem'
          public_key:       '%kernel.project_dir%/config/jwt/public.pem'
          pass_phrase:      'your pass phrase' 
          token_ttl:        3600
      

      并确保在“access_control”上删除该行:

      - { path: ^/api/, roles: IS_AUTHENTICATED_FULLY }

      result without token

      result with Bearer {your token}

      【讨论】:

        猜你喜欢
        • 2019-01-27
        • 2017-12-03
        • 2019-09-23
        • 1970-01-01
        • 2014-11-10
        • 2021-02-20
        • 2020-11-30
        • 2018-06-11
        • 1970-01-01
        相关资源
        最近更新 更多