Я сделал систему аутентификации с LexikJWTBundle, ниже мой security.yml, мой service.yml и мой config.yml
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
providers:
fos_userbundle:
id: fos_user.user_provider.username
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
firewalls:
login:
pattern: ^/api/login
stateless: true
anonymous: true
provider: fos_userbundle
logout: true
form_login:
check_path: /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
register:
pattern: ^/api/register
stateless: true
anonymous: true
register-admin:
pattern: ^/api/adminregister
stateless: true
anonymous: true
api:
pattern: ^/api
stateless: true
anonymous: true
provider: fos_userbundle
guard:
authenticators:
- jwt_token_authenticator
admin-api:
pattern: ^/api/admin
provider: fos_userbundle
stateless: true
anonymous: true
guard:
authenticators:
- jwt_token_authenticator
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
access_control:
- { path: ^/api/login_check, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/adminregister, roles: IS_AUTHENTICATED_ANONYMOUSLY, ips: 127.0.0.1, host: localhost }
- { path: ^/api/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/, roles: [IS_AUTHENTICATED_FULLY, ROLE_USER] }
- { path: ^/api/admin/, roles: [IS_AUTHENTICATED_FULLY, ROLE_ADMIN] }
- { path: ^/api/admin/users, roles: [IS_AUTHENTICATED_FULLY, ROLE_SUPER_ADMIN] }
и service.yml
service.yml
# Learn more about services, parameters and containers at
# https://symfony.com/doc/current/service_container.html
parameters:
#parameter_name: value
services:
# default configuration for services in *this* file
_defaults:
# automatically injects dependencies in your services
autowire: true
# automatically registers your services as commands, event subscribers, etc.
autoconfigure: true
# this means you cannot fetch services directly from the container via $container->get()
# if you need to do this, you can override this setting on individual services
public: false
# makes classes in src/AppBundle available to be used as services
# this creates a service per class whose id is the fully-qualified class name
AppBundle\:
resource: '../../src/AppBundle/*'
# you can exclude directories or files
# but if a service is unused, it's removed anyway
exclude: '../../src/AppBundle/{Entity,Repository,Tests}'
# controllers are imported separately to make sure they're private
# and have a tag that allows actions to type-hint services
AppBundle\Controller\:
resource: '../../src/AppBundle/Controller'
public: true
tags: ['controller.service_arguments']
# add more services, or override services that need manual wiring
# AppBundle\Service\ExampleService:
# arguments:
# $someArgument: 'some_value'
jwt_token_authenticator:
class: AppBundle\Security\JwtTokenAuthenticator
arguments: ['@lexik_jwt_authentication.encoder.lcobucci', '@doctrine.orm.entity_manager']
#service for cors preflight event
AppBundle\Event\Listener\:
resource: '../../src/AppBundle/Event/Listener/'
tags:
- { name: kernel.event_listener, event: kernel.response }
и config.yml
config.yml
// I've only put the lexik config
lexik_jwt_authentication:
secret_key: "%kernel.project_dir%/config/jwt/private.pem" # required for token creation
public_key: "%kernel.project_dir%/config/jwt/private.pem" # required for token verification
pass_phrase: "%user_pass%" # required for token creation, usage of an environment variable is recommended
token_ttl: 36000
user_identity_field: username # key under which the user identity will be stored in the token payload
clock_skew: 0
# token encoding/decoding settings
encoder:
# token encoder/decoder service - default implementation based on the lcobucci/jwt library
service: lexik_jwt_authentication.encoder.lcobucci
# encryption algorithm used by the encoder service
signature_algorithm: RS256
# token extraction settings
token_extractors:
# look for a token as Authorization Header
authorization_header:
enabled: true
prefix: Bearer
name: Authorization
# check token in a cookie
cookie:
enabled: false
name: BEARER
# check token in query string parameter
query_parameter:
enabled: false
name: bearer
это функция для сторожевого аутентификатора
class JwtTokenAuthenticator extends AbstractGuardAuthenticator
{
private $jwtEncoder;
private $em;
public function __construct(JWTEncoderInterface $jwtEncoder, EntityManager $em)
{
$this->jwtEncoder = $jwtEncoder;
$this->em = $em;
}
public function supports(Request $request)
{
// look for header "Authorization: Bearer <token>"
return $request->headers->has('Authorization')
&& 0 === strpos($request->headers->get('Authorization'), 'Bearer ');
}
public function getCredentials(Request $request)
{
$extractor = new AuthorizationHeaderTokenExtractor(
'Bearer',
'Authorization'
);
$token = $extractor->extract($request);
if (!$token) {
return new JsonResponse([
"errorMessage" => "The token doesn't exist in authorization header please provide it like (Authorization: Bearer token)"
]);
}
return $token;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
var_dump($credentials);
try {
$data = $this->jwtEncoder->decode($credentials);
} catch (JWTDecodeFailureException $e) {
$reason = $e->getReason();
switch ($reason) {
case 'invalid_token':
// throw new InvalidTokenException();
throw new CustomUserMessageAuthenticationException('The token is invalid');
break;
case 'unverified_token':
throw new CustomUserMessageAuthenticationException('Unverified Token');
break;
case 'expired_token':
// throw new ExpiredTokenException();
throw new CustomUserMessageAuthenticationException('The token is expired');
break;
default:
throw new MissingTokenException();
break;
}
}
$username = $data['username'];
return $this->em
->getRepository('AppBundle:User')
->findOneBy(['username' => $username]);
}
public function checkCredentials($credentials, UserInterface $user)
{
return true;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
return new JsonResponse([
'message' => $exception->getMessageKey()
], 401);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
}
public function supportsRememberMe()
{
return false;
}
public function start(Request $request, AuthenticationException $authException = NULL)
{
throw new \Exception('Not used: entry_point from other authentication is used');
}
}
токен существует в заголовке, но когда я пытаюсь его декодировать, у меня появляется ошибка {"message": "The token is invalid"}
даже если токен подтвержден jwt.io, пожалуйста, мне нужна помощь, вот уже почти 3 недели я пытаюсь справиться с этой проблемой