Symfony 4 API Platform+LexikJWTAuthenticationBundle:凭证错误

Symfony 4 API Platform+LexikJWTAuthenticationBundle : Bad credentials

我正在尝试使用 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

密钥也已创建:

有什么建议,解决方案吗?提前致谢

我认为 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:

LexikJTW 包之前的 /api 就像这个演示:https://demo.api-platform.com

如何取回 api 平台并获得令牌作为响应? 我 运行 没有想法和选择...

我解决了。 我在 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."
}

但那是另外一回事了。我会将其标记为已解决。希望对大家有帮助。

这是一个对我有用的例子,使用 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}