使用Laravel Sanctum认证Pusher时出现401未授权错误求助
Laravel Sanctum + Pusher 401未授权问题解决方案
问题现象
使用Laravel Sanctum完成Pusher频道认证时,收到401未授权响应,错误信息如下:
[Error] Pusher : : ["Error: Unable to retrieve auth string from channel-authorization endpoint - received status: 401 from http://localhost:8000/broadcasting/auth. Clients must be authorized to join private or presence channels. See: https://pusher.com/docs/channels/server_api/authorizing-users/"]
已配置BroadcastServiceProvider使用Sanctum认证守卫:
<?php namespace App\Providers; use Illuminate\Support\Facades\Broadcast; use Illuminate\Support\ServiceProvider; class BroadcastServiceProvider extends ServiceProvider { /** * Bootstrap any application services. * * @return void */ public function boot() { Broadcast::routes(['middleware' => ['auth:sanctum']]); require base_path('routes/channels.php'); } }
前端已传递X-CSRF-TOKEN头,尝试替换为Bearer格式的Authorization头后,问题仍未解决,前端代码如下:
import axios from '@/lib/axios' import Echo from 'laravel-echo' import Pusher from 'pusher-js' import Cookies from 'js-cookie' export default async function echo() { if (typeof window !== 'undefined') { Pusher.logToConsole = true // const csrf = () => axios.get('/sanctum/csrf-cookie') const key = '<redacted>' const pusherClient = new Pusher(key, { cluster: 'eu', forceTLS: true, channelAuthorization: { endpoint: 'http://localhost:8000/broadcasting/auth', headers: { Accept: 'application/json', 'X-CSRF-TOKEN': Cookies.get('XSRF-TOKEN'), }, }, }) window.Echo = new Echo({ broadcaster: 'pusher', client: pusherClient, }) window.Echo.private('chat').listen( 'App\\Events\\PrivateMessageSent', e => { console.log(e) }, ) } }
解决方案
1. 完善前端授权头配置
Sanctum需要Authorization: Bearer {token}头完成API请求认证,前端需将登录后获取的有效令牌加入Pusher的授权请求头:
// 替换为你实际存储令牌的键名(比如登录后存在Cookies或localStorage中的令牌) const token = Cookies.get('auth_token'); const pusherClient = new Pusher(key, { cluster: 'eu', forceTLS: true, channelAuthorization: { endpoint: 'http://localhost:8000/broadcasting/auth', headers: { Accept: 'application/json', 'X-CSRF-TOKEN': Cookies.get('XSRF-TOKEN'), 'Authorization': `Bearer ${token}` // 新增Bearer令牌头 }, }, })
2. 校验Sanctum核心配置
- 打开
config/sanctum.php,确保stateful数组包含前端域名(本地开发需包含前端端口):
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,127.0.0.1:8000,127.0.0.1:3000')),
- 检查
.env文件中SESSION_DOMAIN设置,本地开发可设为.localhost
3. 确认频道授权规则
打开routes/channels.php,确保chat私有频道的授权逻辑允许当前用户访问:
Broadcast::channel('chat', function ($user) { // 这里返回true表示允许用户加入频道,可根据业务需求添加自定义校验(比如用户权限) return true; });
若返回false或未定义该频道的授权规则,会直接返回401。
4. 配置跨域支持
如果前后端跨域部署,需确保config/cors.php配置正确:
'paths' => ['api/*', 'sanctum/csrf-cookie', 'broadcasting/auth'], 'allowed_methods' => ['*'], 'allowed_origins' => ['*'], // 生产环境替换为具体前端域名 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, 'supports_credentials' => true,
注意supports_credentials必须设为true,否则跨域请求无法携带Cookies和Authorization头。
5. 确保用户已完成登录
Pusher频道授权需要用户处于登录状态,前端初始化Echo前需校验令牌是否存在:
export default async function echo() { if (typeof window !== 'undefined') { const token = Cookies.get('auth_token'); if (!token) return; // 用户未登录则终止初始化 Pusher.logToConsole = true // ... 后续初始化代码 } }
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

