Dan*_*nte 3 laravel laravel-echo laravel-websockets
我知道我不是第一个为此苦苦挣扎的人。但几天后,经过很多相关的问题,我觉得我的案子值得它自己的问题:)。
我有一个可用的 websocket 解决方案,包括 Laravel Websockets ( https://beyondco.de/docs/laravel-websockets/getting-started/introduction ) 和用于公共频道的 Laravel Echo 。我的客户端应用程序是一个 vue-cli 应用程序,连接到服务器+公共频道上的广播消息效果很好。授权由 Laravel Passport 处理。因此,通过在授权标头中发送承载令牌,后端应用程序可以知道用户是否已通过身份验证。
然而,我正在努力让私人频道正常工作。尝试进行身份验证总是给我这个错误:
Access to XMLHttpRequest at 'https://my-app.test/broadcasting/auth' from origin 'https://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Run Code Online (Sandbox Code Playgroud)
我知道当我遇到服务器问题时会出现此 CORS 错误,因此我尝试在 Insomnia 中调试请求。然而,当模仿 Insomnia 中的请求时,它会给出响应 200 以及预期的结果:
我一直在阅读一些指南和 stackoverflow 问题,但找不到类似的内容。回到它可能是 CORS 问题,但我认为情况并非如此。我的 OPTIONS 请求返回得很好。
为了完整起见,我还添加了一些可能有助于调试的代码。
我的广播服务提供商
public function boot()
{
Broadcast::routes(['middleware' => ['auth:api']]);
require base_path('routes/channels.php');
}
Run Code Online (Sandbox Code Playgroud)
我的频道.php
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('App.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
Run Code Online (Sandbox Code Playgroud)
客户端
this.echoClient = new Echo({
broadcaster: 'pusher',
key: process.env.VUE_APP_WEBSOCKETS_APP_ID,
wsHost: process.env.VUE_APP_WEBSOCKETS_URL,
wssPort: 6001,
// forceTLS: true,
disableStats: true,
authEndpoint: process.env.VUE_APP_SERVER_URL + '/broadcasting/auth',
auth: {
headers: {
Authorization: "Bearer " + this.$store.state.auth.auth_token
}
}
})
// this one works!!
this.echoClient.channel('App.User')
.listen('UpdatePosts', (e) => {
console.log('event received')
console.log(e)
})
// private channels don't work ... :'(
this.echoClient.private('App.User.' + this.user.id)
.listen('UpdatePosts', function(e) {
console.log(e)
})
Run Code Online (Sandbox Code Playgroud)
对于任何在这个问题上苦苦挣扎的人。对我来说,解决方案是将 api 前缀添加到广播::auth 方法中。
public function boot()
{
Broadcast::routes(['prefix' => 'api', 'middleware' => ['auth:api']]);
require base_path('routes/channels.php');
}
Run Code Online (Sandbox Code Playgroud)
当然你需要在客户端正确设置 api 前缀:
authEndpoint: process.env.VUE_APP_SERVER_URL + '/api/broadcasting/auth',
Run Code Online (Sandbox Code Playgroud)
我想区别在于,当你为 Laravel api 添加前缀时,我们会明确告诉服务器放弃 Web 中间件。
我仍然不太明白为什么 Insomnia 的请求会成功,因为没有设置 x-csrf 标头。Insomnia 确实发送了一个 cookie 标头。也许这就是它在那里工作的原因。
编辑
@Tippin 在 laracasts 论坛上提供的解决方案。
补充一下答案,这毕竟是 CORS 问题。
https://github.com/fruitcake/laravel-cors
在广播路由上添加 API 前缀根本不会改变中间件,因此不会将其放在 api 中间件组中。我认为正在发生的事情是您可能安装了 cors 软件包,并且在允许的路径中,您有类似 api/* 的内容,因此只需添加该前缀即可解决您的问题。否则,您可以将默认广播添加到白名单(假设您将该包用于 CORS):
/*
* You can enable CORS for 1 or multiple paths.
* Example: ['api/*']
*/
'paths' => ['api/*', 'broadcasting/auth'],
Run Code Online (Sandbox Code Playgroud)
https://github.com/fruitcake/laravel-cors/blob/master/config/cors.php
| 归档时间: |
|
| 查看次数: |
4896 次 |
| 最近记录: |