https://symfony.com/doc/current/security/guard_authentication.html 根据文档,如果客户端访问需要身份验证的 URI/资源,则将调用 start 函数,但未发送身份验证详细信息但我已通过带有请求的令牌。我不确定我在哪里做错了,任何人都可以建议我.. 我尝试了很多搜索,但仍然找不到任何解决方案。
我还尝试在请求上打印令牌并且它工作正常......所以我认为问题是别的,令牌在请求中传递得很好。
如果我将防火墙 - 主 - 模式更改为 ^/gateway/v1/ 它会给我
访问被拒绝,用户未完全认证;重定向到身份验证入口点。
我的日志的输出
[Mon Nov 19 22:52:34 2018] 127.0.0.1:57773 [401]: /gateway/v1/products
2018-11-19T21:52:39+00:00 [info] Matched route "app_product_products".
2018-11-19T21:52:39+00:00 [debug] Checking for guard authentication credentials.
2018-11-19T21:52:39+00:00 [debug] Calling getCredentials() on guard authenticator.
2018-11-19T21:52:39+00:00 [info] An AuthenticationException was thrown; redirecting to authentication entry point.
2018-11-19T21:52:39+00:00 [debug] Calling Authentication entry point.
[Mon Nov 19 22:52:39 2018] 127.0.0.1:57777 [401]: /gateway/v1/products
TokenController -> 生成令牌(http://127.0.0.1:8000/gateway/v1/token)
public function token(Request $request)
{
$data =json_decode($request->getContent(),true);
foreach ($this->getCustomers() as $customer){
if($customer["username"]==$data['username'] && $customer["password"]==$data['password']){
// $token = $this->tokenManager->create($customer["username"]);
// $jwtManager = $this->container->get('lexik_jwt_authentication.jwt_manager');
// return new JsonResponse(['token' => $this->getRandomId()]);
// $token = $this->get('lexik_jwt_authentication.jwt_manager')->create($user);
$token = $this->get('lexik_jwt_authentication.encoder')->encode([
'username' => $customer["username"],
'role' => "IS_AUTHENTICATED_FULLY",
'exp' => time() + 3600 // 1 hour expiration
]);
//$User->setApiToken($token);
return new JsonResponse(['token' => $token]);
}
}
//return $response;
return $this->handleView("Customer Not Exits");
}
配置/包/security.yaml
security:
# ...
#
# encoders:
# App\Security\Username:
# algorithm: argon2i
firewalls:
main:
pattern: ^/gateway/v1/token
stateless: true
anonymous: true
json_login:
check_path: /gateway/v1/token
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/gateway/v1/
stateless: true
guard:
authenticators:
- jwt_token_authenticator
access_control:
- { path: ^/gateway/v1/token, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/gateway/v1/, roles: IS_AUTHENTICATED_FULLY }
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
id: App\Security\UserProvider
src/Security/JwtTokenAuthenticator.php
<?php
namespace App\Security;
use Doctrine\ORM\EntityManager;
use Lexik\Bundle\JWTAuthenticationBundle\Encoder\JWTEncoderInterface;
use Lexik\Bundle\JWTAuthenticationBundle\Exception\JWTDecodeFailureException;
use Lexik\Bundle\JWTAuthenticationBundle\TokenExtractor\AuthorizationHeaderTokenExtractor;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\HttpFoundation\Request;
class JwtTokenAuthenticator extends AbstractGuardAuthenticator
{
private $jwtEncoder;
private $em;
public function __construct(JWTEncoderInterface $jwtEncoder/*, EntityManager $em*/)
{
$this->jwtEncoder = $jwtEncoder;
/*$this->em = $em;*/
}
public function getCredentials(Request $request)
{
$extractor = new AuthorizationHeaderTokenExtractor(
'Bearer',
'Authorization'
);
$token = $extractor->extract($request);
// return new JsonResponse($token);
if (!$token) {
return new JsonResponse("token not specified") ;
}
return $token;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
try {
$data = $this->jwtEncoder->decode($credentials);
// return new JsonResponse($data);
} catch (JWTDecodeFailureException $e) {
throw new CustomUserMessageAuthenticationException('Invalid Token');
}
$username = $data['username'];
//$role = $data['role'];
//echo $role;
// $user=new Username();
//return $user->findbyusername($username);
/*return true $this->em
->getRepository('AppBundle:User')
->findOneBy(['username' => $username]);*/
return $userProvider->loadUserByUsername($username);
}
public function checkCredentials($credentials, UserInterface $user)
{
return true;
// TODO: Implement checkCredentials() method.
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$data = array(
'message' => strtr($exception->getMessageKey(), $exception->getMessageData())
// or to translate this message
// $this->translator->trans($exception->getMessageKey(), $exception->getMessageData())
);
return new JsonResponse($data, Response::HTTP_FORBIDDEN);
// TODO: Implement onAuthenticationFailure() method.
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
return null;
// TODO: Implement onAuthenticationSuccess() method.
}
public function supportsRememberMe()
{
// TODO: Implement supportsRememberMe() method.
}
public function start(Request $request, AuthenticationException $authException = null)
{
$data = array(
// you might translate this message
'message' => 'Authentication Required'
);
return new JsonResponse($data, Response::HTTP_UNAUTHORIZED);
// TODO: Implement start() method.
}
public function supports(Request $request, AuthenticationException $authException = null)
{
if ($request->getPathInfo() != '/gateway/v1/token') {
return false;
}
/*
return new JsonResponse([
'error' => 'auth required'
], 401);
echo "getCredential: ";
$extractor = new AuthorizationHeaderTokenExtractor(
'Bearer',
'Authorization'
);
$token = $extractor->extract($request);
if (!$token) {
return new JsonResponse("token not specified") ;
}
return new JsonResponse($token);
// TODO: Implement start() method.*/
}
}