首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Laravel轮胎设计/jwt-auth问题

Laravel轮胎设计/jwt-auth问题
EN

Stack Overflow用户
提问于 2017-10-18 11:23:45
回答 3查看 6.9K关注 0票数 0

我正在使用我的API设置一个身份验证路由。我使用laravel5.5和tymondesigns/jWT-auth1.0.0-rc.1和Postman来与API进行交互。

身份验证路由/方法似乎有效:

代码语言:javascript
复制
/**
 * Authenticates a json request, generating a token.
 *
 * @param Request $request
 * @return JsonResponse
 */
public function authenticate(Request $request)
{
    // grab credentials from the request
    $credentials = $request->only('email', 'password');

    try {
        // attempt to verify the credentials and create a token for the user
        if (! $token = JWTAuth::attempt($credentials)) {
            return response()->json(
                [
                    'error' => 'Invalid credentials.',
                    'detail' => 'Please use your email and password to generate a token.'
                ],
                401);
        }
    } catch (JWTException $e) {
        // something went wrong whilst attempting to encode the token
        return response()->json(
            [
                'error' => 'Could not create token',
                'detail' => 'There was an internal problem and your token could not be created.'
            ], 500
        );
    }

    // all good so return the token
    return response()->json(compact('token'));
}

Postman请求返回(似乎是)一个有效的响应,例如:

代码语言:javascript
复制
{
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vc29sZGVyc3RhcmFwaS5jb20ubG9jYWwvYXBpL2F1dGhlbnRpY2F0ZSIsImlhdCI6MTUwNzg4NjU2OSwiZXhwIjoxNTA3ODkwMTY5LCJuYmYiOjE1MDc4ODY1NjksImp0aSI6IkpFWjBkc0dNbEVydXRHcFciLCJzdWIiOiIwNzk2MjhDMC03QjBDLTExRTYtODRERC1DQjAzMzVGN0JBNUQiLCJwcnYiOiI4N2UwYWYxZWY5ZmQxNTgxMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIn0.Dl2EEaYZx3H5XXG9WUcPXYKuma0ZjCvcCsb99hgB6O4"
}

首先,出于基本测试的目的,我使用GET将其添加到一个操作中,其后缀如下:

?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vc29sZGVyc3RhcmFwaS5jb20ubG9jYWwvYXBpL2F1dGhlbnRpY2F0ZSIsImlhdCI6MTUwNzg4NjU2OSwiZXhwIjoxNTA3ODkwMTY5LCJuYmYiOjE1MDc4ODY1NjksImp0aSI6IkpFWjBkc0dNbEVydXRHcFciLCJzdWIiOiIwNzk2MjhDMC03QjBDLTExRTYtODRERC1DQjAzMzVGN0JBNUQiLCJwcnYiOiI4N2UwYWYxZWY5ZmQxNTgxMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIn0.Dl2EEaYZx3H5XXG9WUcPXYKuma0ZjCvcCsb99hgB6O4

为了测试这一点,如果我做了以下操作:

代码语言:javascript
复制
public function globalObjects(Request $request): JsonResponse {
    var_dump(JWTAuth::parseToken()->authenticate(), JWTAuth::getToken()); exit;

   // ... later code that never gets reached
}

我得到以下信息:

代码语言:javascript
复制
bool(false) object(Tymon\JWTAuth\Token)#809 (1) { ["value":"Tymon\JWTAuth\Token":private]=> string(384) "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vc29sZGVyc3RhcmFwaS5jb20ubG9jYWwvYXBpL2F1dGhlbnRpY2F0ZSIsImlhdCI6MTUwNzg4NjU2OSwiZXhwIjoxNTA3ODkwMTY5LCJuYmYiOjE1MDc4ODY1NjksImp0aSI6IkpFWjBkc0dNbEVydXRHcFciLCJzdWIiOiIwNzk2MjhDMC03QjBDLTExRTYtODRERC1DQjAzMzVGN0JBNUQiLCJwcnYiOiI4N2UwYWYxZWY5ZmQxNTgxMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIn0.Dl2EEaYZx3H5XXG9WUcPXYKuma0ZjCvcCsb99hgB6O4" }

。。如:

  • 我收到了令牌
  • 它找不到用户。

注意事项:

  • 我的主键是id,但是它是UUID,所以二进制(16).因此:
  • 我将标识符设置为:‘=>’电子邮件‘

以下请求:这是\config\jwt.php

代码语言:javascript
复制
return [
    'secret' => env('JWT_SECRET', 'AqAWUTYISA56lrl2vcRtZQn4M4zk9onl'),
    'ttl' => 60,
    'refresh_ttl' => 20160,
    'algo' => 'HS256',
    'user' => 'App\User',
    'identifier' => 'email',
    'required_claims' => ['iss', 'iat', 'exp', 'nbf', 'sub', 'jti'],
    'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),
    'providers' => [
        'user' => 'Tymon\JWTAuth\Providers\User\EloquentUserAdapter',
        'jwt' => 'Tymon\JWTAuth\Providers\JWT\Namshi',
        'auth' => 'Tymon\JWTAuth\Providers\Auth\Illuminate',
        'storage' => 'Tymon\JWTAuth\Providers\Storage\Illuminate',

    ],

];

谢谢

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-10-18 21:23:20

答案是:“这与当前状态下的这个特性不兼容,如果不自己扩展它”。

我希望这能帮助其他人使用UUID作为主键。如果不编辑供应商的项目或者扩展.但是,这是一个简单的解决办法。

我将与包作者提出这一点,并希望找到一个更永久的解决方案。然而,这里有一个解决办法:

背景:

  • UUID作为二进制(16) id列存储在数据库中。
  • 这不是人类可读的/文本友好的。
  • 为了解决这个问题,id_text字段作为自动生成的mysql字段存在。
  • 注意-您不应该使用这些搜索(它严重地强调了数据库)
  • 这些是文本可读的,因此..。可以很容易地在表格等中使用
  • 为了便于翻译,我创建了一个UuidHelper。

JWT中的问题:

  • 身份验证函数尝试将id_text解码为id。
  • 很明显,这总是失败的

文件中的\vendor\tymon\jwt-auth\src\JWTAuth.php

代码语言:javascript
复制
/**
 * Authenticate a user via a token.
 *
 * @return \Tymon\JWTAuth\Contracts\JWTSubject|false
 */
public function authenticate()
{
    $id_text = $this->getPayload()->get('sub');

    $uuid_helper = new UuidHelper();
    $id = $uuid_helper->textIdToId($id_text);

    if (! $this->auth->byId($id)) {
        return false;
    }

    return $this->user();
}

文档并不是最清晰的,所以我认为'identifier' => 'email'会避开这个问题。事实并非如此。我会把这个反馈给作者

修改核心只是一个练习..。我确信这个类可以扩展,我很快就会尝试这样做。编辑源当然是次优的大多数情况。

不过,我希望这次挖掘能帮助人们了解这个问题。

票数 0
EN

Stack Overflow用户

发布于 2017-11-03 20:29:25

下面是我在API中使用的解决方案,效果非常好。

首先重写类Tymon\JWTAuth\Providers\Auth\Illuminate::class

代码语言:javascript
复制
<?php


namespace Scryba\Code\Laravel\Providers\Auth\Jwt;

use Tymon\JWTAuth\Contracts\Providers\Auth;
use Illuminate\Contracts\Auth\Guard as GuardContract;

class Illuminate implements Auth
{
/**
 * The authentication guard.
 *
 * @var \Illuminate\Contracts\Auth\Guard
 */
protected $auth;

/**
 * Constructor.
 *
 * @param  \Illuminate\Contracts\Auth\Guard  $auth
 *
 * @return void
 */
public function __construct(GuardContract $auth)
{
    $this->auth = $auth;
}

/**
 * Check a user's credentials.
 *
 * @param  array  $credentials
 *
 * @return bool
 */
public function byCredentials(array $credentials)
{
    return $this->auth->once($credentials);
}

/**
 * Authenticate a user via the id.
 *
 * @param  mixed  $id
 *
 * @return bool
 */
public function byId($id)
{
    //you can see i added hex2bin($id)because i save my UUID primary key as 
    //binary(16)
    return $this->auth->onceUsingId(hex2bin($id));
}

/**
 * Get the currently authenticated user.
 *
 * @return mixed
 */
public function user()
{
    return $this->auth->user();
}
}

然后将\config\jwt.php文件更新为

代码语言:javascript
复制
 'providers' => [

    /*
    |--------------------------------------------------------------------------
    | JWT Provider
    |--------------------------------------------------------------------------
    |
    | Specify the provider that is used to create and decode the tokens.
    |
    */

    'jwt' => Tymon\JWTAuth\Providers\JWT\Namshi::class,

    /*
    |--------------------------------------------------------------------------
    | Authentication Provider
    |--------------------------------------------------------------------------
    |
    | Specify the provider that is used to authenticate users.
    |
    */

    //'auth' => Tymon\JWTAuth\Providers\Auth\Illuminate::class,
    'auth' => Scryba\Code\Laravel\Providers\Auth\Jwt\Illuminate::class,

    /*
    |--------------------------------------------------------------------------
    | Storage Provider
    |--------------------------------------------------------------------------
    |
    | Specify the provider that is used to store tokens in the blacklist.
    |
    */

    'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class,

],

在我的路线档案里

代码语言:javascript
复制
////// Protected methods (requires Authenticatication)
        $api->group(
            [
                'middleware' => ['api.auth'],
                'providers' => ['jwt'],

            ],function($api){

        $api->resource('cars', 'CarController', ['only' => [
            'index' ,'show'
        ]]);

        });

因此,在您的示例中,源文件\vendor\tymon\jwt-auth\src\JWTAuth.php保持原样,并在适用的情况下在自定义类中编写如下代码。

代码语言:javascript
复制
/**
* Authenticate a user via the id.
*
* @param  mixed  $id
*
* @return bool
*/
public function byId($id)
{
   $id_text = $this->getPayload()->get('sub');

   $uuid_helper = new UuidHelper();
   $id = $uuid_helper->textIdToId($id_text);

  return $this->auth->onceUsingId($id);
}
票数 2
EN

Stack Overflow用户

发布于 2017-10-18 15:40:27

您接收到令牌,但未正确解析,您需要检查令牌解析是否成功。

代码语言:javascript
复制
if (! $auth = JWTAuth::parseToken();) {
    throw Exception('JWTAuth unable to parse token from request');
}
dd(\Auth::id());

我建议您转到您的kernal.php并在受保护的$routeMiddleware数组中添加以下行

代码语言:javascript
复制
'jwt.auth' => 'Tymon\JWTAuth\Middleware\GetUserFromToken',
'jwt.refresh' => 'Tymon\JWTAuth\Middleware\RefreshToken',

然后回到您的路线,像中间件一样使用它来进行如下身份验证。

代码语言:javascript
复制
 Route::group(['middleware' => 'jwt.auth'], function () {
  // Your routes here that you want to protect
        Route::get('foo', function () {
        return 'Hello World';
             });
     ]):

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46809043

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档