【问题标题】:Is this a proper Laravel Passport use case?这是一个合适的 Laravel Passport 用例吗?
【发布时间】:2019-05-30 11:02:09
【问题描述】:

因此,将我的应用程序视为 CMS(laravel 5.7)。我正在慢慢添加更多的 javascript 以使其更具反应性。所以我有通常的验证逻辑来​​确保用户登录等等。但是现在当我使用 Vue 提交评论负载时,它看起来有点像这样:

所以看看这个,任何人都可以将 this.user.id 更改/模拟为任何数字,我还想发送一个带有有效负载的登录令牌,然后在服务器收到发布请求后在后端进行验证.

在后端,理想情况下,我希望有某种安全措施来检查用户的 api_token 是否与 this.user.id 匹配,以确保 user.id 不会在前端被模拟。

我读了这部分:https://laravel.com/docs/5.7/passport#consuming-your-api-with-javascript

它的一部分说:

此 Passport 中间件会将 laravel_token cookie 附加到您的传出响应中。此 cookie 包含一个加密的 JWT,Passport 将使用它来验证来自您的 JavaScript 应用程序的 API 请求。现在,您可以在不显式传递访问令牌的情况下向应用程序的 API 发出请求:

但我仍然有点不确定 JWT 最初是如何生成的。我没有添加用于创建令牌 crud 的 vue 组件,因为我希望它自动完成。我想我有点想太多了..

这是 Laravel Passport 的好用例吗?我正在浏览教程,现在我不需要自定义 oauth 令牌创建和所有的 crud。我只想在用户端保存一个唯一令牌,该令牌可以过期,但也可用于验证请求。我在使用 Passport 时是否走在正确的轨道上,还是应该使用不同的方法?

postComment(){
axios.post('/api/view/' + this.query.id+'/comment',{
id: this.user.id,
body: this.commentBox
})
.then((response) =>{
//Unshift places data to top of array, shifts everything else down.
this.comments.unshift(response.data);
this.commentBox = '';
document.getElementById("commentBox").value = "";
flash

('Comment posted successfully');
})
.catch((error) => {
console.log(error);
})
},

更新 - 回复 Jeff

嗨!感谢您的回答。它不是一个 SPA(将来可能会),但评论框和评论部分也与 websockets 集成,上面有一个 laravel Echo 实例。

我想我不确定的地方是它的安全性。 我将带有:user="{{Auth::check() ? Auth::user()->toJson() : 'null'}}" 的用户道具传递到包含postComment() 函数的vue 组件中。

这就是id: this.user.id 的来源。路由在 ['api'] 的路由中间件组中的 api.php 中定义,如下所示:

Route::group(['middleware' => ['api']], function(){
Route::post('/view/{query}/comment','CommentController@store');
});

在调用服务来创建评论的我的控制器中,$request

public function makejson(createNewCommentRequest $request, Query $query){
$comment = $query->comments()->create([
'body' => $request->get('body'),
])->user()->associate(User::find($request->id));
$id = $comment->id;
$comment->save();
}

createNewCommentRequest 是一个 FormRequest 类。

现在 authorize() 函数只检查 request()->id 是否为 int:

public function authorize()
{
if(is_int(request()->id)){
return true;
}
return false;
}

如果我从那里记录 request(),它输出的只是:

array ( 'id' => 1, 'body' => 'gg', )

我认为我需要添加逻辑来根据用户令牌和 request() 是否产生相同的用户 ID 来授权请求​​?我想避免有人可以使用其他用户 ID 修改发布请求和评论的情况。

在 devtools 的网络部分,在请求标头中,我看到它推送了一个 laravel_token cookie。我假设laravel_token 是存储用户会话的内容?如果是这样,如何根据该令牌进行验证?

我在玩耍并添加了路线:

Route::get('/token', function() {
return Auth::user()->createToken('test');
});

当我去那里时,我得到了以下信息:

{
"accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImE4NDE2NGVkM2NkODc5NDY3MzAxYzUyNmVkN2MyMGViZTllNzJlMGMzMjRiMmExNWYzZDgwZGNmMzEzMDk1MTRmNTY1NGMxYWUwMTE2ZGRkIn0.eyJhdWQiOiIxIiwianRpIjoiYTg0MTY0ZWQzY2Q4Nzk0NjczMDFjNTI2ZWQ3YzIwZWJlOWU3MmUwYzMyNGIyYTE1ZjNkODBkY2YzMTMwOTUxNGY1NjU0YzFhZTAxMTZkZGQiLCJpYXQiOjE1NDY1NTQzNDEsIm5iZiI6MTU0NjU1NDM0MSwiZXhwIjoxNTc4MDkwMzQwLCJzdWIiOiIxIiwic2NvcGVzIjpbXX0.NMETCBkOrMQGUsXlcas6CvTFJ0xRC8v4AJzC5GtWANdl8YsPBGlyCozMe1OGc8Fnq8GC_GZFkKmMT27umeVcSyaWriZB139kvtWzY6ylZ300vfa5iI-4XC_tJKoyuwDEofqMLDA4nyrtMrp_9YGqPcg6ddR61BLqdvfr0y3Nm5WWkyMqBzjKV-HFyuR0PyPQbnLtQGCzRFUQWbV4XWvH2rDgeI71S6EwmjP7J1aDA2UBVprGqNXdTbxWpSINMkZcgrDvl4hdqNzet-OwB2lu2453R-xKiJkl8ezwEqkURwMj70G-t9NjQGIBInoZ-d3gM2C3J9mEWMB5lyfSMaKzhrsnObgEHcotORw6jWNsDgRUxIipJrSJJ0OLx29LHBjkZWIWIrtsMClCGtLXURBzkP-Oc-O9Xa38m8m6O9z-P8i6craikAIckv9YutmYHIXCAFQN2cAe2mmKp7ds1--HWN_P5qqw6ytuR268_MbexxGDTyq8KzUYRBjtkgVyhuVsS7lDgUHgXvJfHNmdCulpiPhmbtviPfWaZM19likSjKHLTpIn2PpfTflddfhB9Eb4X24wGH7Y5hwxASe7gDs_R707LphS1EH4cTE8p2XW_lLv0jo89ep9IUPUO27pWLsqabt8uTr5OoKQeNZmXT6XiJ9tK3HhRgvIt7DYt8vqlRw",
    "token": {
    "id": "a84164ed3cd879467301c526ed7c20ebe9e72e0c324b2a15f3d80dcf31309514f5654c1ae0116ddd",
    "user_id": 1,
    "client_id": 1,
    "name": "lol",
    "scopes": [],
    "revoked": false,
    "created_at": "2019-01-03 22:25:40",
    "updated_at": "2019-01-03 22:25:40",
    "expires_at": "2020-01-03 22:25:40"
    }
    }

现在在 Postman 中,当我向以下位置发送 get 请求时:

Route::middleware('auth:api')->get('/user', function (Request $request){return $request->user();});

我为变量中捕获的字符串添加了一个 Bearer Token 类型的授权标头:accessToken。作为回报,我得到了用户,没问题。但是 accessToken 是在哪里以及如何生成的?没有保存在数据库中?

【问题讨论】:

  • 也许Consuming your API with Javascript 是您要找的?
  • @Mozammil 感谢您的评论 - 我已经在我的帖子中引用了相同的链接/部分,但不确定 JWT 最初是如何生成的。

标签: laravel oauth laravel-passport


【解决方案1】:

从令牌中获取 Laravel 提供给你的用户 ID,而不是从前端发送。您还可以检查分配给令牌的范围:

Route::post('/api/view/{query}/comment', function (Request $request, Query $query) {
    if ($request->user()->tokenCan('comment-on-queries')) {
        $query->comments()->create([
            'body' => $request->get('body'),
            'user_id' => $request->user()->id,
        ]);
    }
});

如果这不是单页应用程序,并且只有评论框由 ajax 处理,则默认的 Laravel 脚手架应该通过向 axios 配置添加 CSRF 令牌来处理此问题。在这种情况下,您不需要 Passport,因为用户存储在会话中。尽管如此,不要从前端获取用户ID,从\Auth::id()获取它

这是关键的区别:如果他们使用 PHP 登录,您的服务器会存储一个会话并知道谁登录了。

如果你要创建一个与 Laravel 应用分开的单页应用,你必须依赖 Passport 和令牌来确保用户有权做他们想做的事情。

【讨论】:

  • 嗨@Jeff,感谢您的回复!我在“更新 - 回复杰夫”下的原始问题中发布了回复。非常感谢您的反馈!
【解决方案2】:

想通了,想多了。基本上不需要太多就可以让它工作。

  • 将 CreateFreshApiToken 中间件添加到 app\Http\Kernel.php 中的 web 组。
  • axios 响应将该 cookie 附加到传出响应中
  • api 中间件组必须是“auth:api”。

然后可以通过 request()->user() 调用用户实例,这很棒。

【讨论】:

    猜你喜欢
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-15
    • 1970-01-01
    • 2021-04-10
    相关资源
    最近更新 更多