Laravel Bluesky 支持两种认证方式。完成认证后,两种方式调用 API 的方法是通用的。
| 项目 | App Password | OAuth |
|---|
| 内部类 | LegacyAgent / LegacySession | OAuthAgent / OAuthSession |
| 入口 | Bluesky::login() | Bluesky::withToken(OAuthSession) |
| 私钥 | 不需要 | 需要 BLUESKY_OAUTH_PRIVATE_KEY |
| 用户授权操作 | 不需要 | 需要(在浏览器中批准) |
| 后台执行 | ✅ 擅长 | ✅ 可以(保存 refresh_token) |
| 会话 key | accessJwt / refreshJwt | access_token / refresh_token |
| 是否即将废弃 | 不会 | — |
| 主要用途 | 自动发帖、通知、批处理 | 代表用户操作、Socialite 集成 |
LegacyAgent 这个命名表示的是“OAuth 之前的认证方式”,但 App Password 本身并没有废弃计划。在通知、自动发帖等无需用户操作的场景中,App Password 更简单,也更合适。
BlueskyManager 是 Facade Bluesky 的具体实现。使用 login() 或 withToken() 设置 agent 后,之后的 API 调用在两种认证方式下使用相同的方法。
App Password (LegacyAgent)
认证流程
Bluesky::login()
只需在 .env 中配置 App Password 并调用 login()。
BLUESKY_IDENTIFIER=your-handle.bsky.social
BLUESKY_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx
use Revolution\Bluesky\Facades\Bluesky;
$response = Bluesky::login(
identifier: config('bluesky.identifier'),
password: config('bluesky.password'),
)->post('Hello Bluesky');
复用 LegacySession
如果每次都调用 login(),每次都会产生 API 请求。缓存并复用 session 会更加高效。
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Session\LegacySession;
// 首次登录并保存 session
Bluesky::login(
identifier: config('bluesky.identifier'),
password: config('bluesky.password'),
);
cache()->put('bluesky_session', Bluesky::agent()->session()->toArray(), now()->addDay());
// 之后从缓存中恢复
$session = LegacySession::create(cache('bluesky_session', []));
Bluesky::withToken($session);
// 如果 access token 过期,则刷新
if (! Bluesky::check()) {
Bluesky::refreshSession();
}
$response = Bluesky::post('Hello from cached session');
LegacySession 的主要键
| 键 | 内容 | 方法 |
|---|
accessJwt | access token | token() |
refreshJwt | refresh token | refresh() |
did | Bluesky DID | did() |
handle | handle | handle() |
email | 邮箱地址 | email() |
active | 账号是否处于活跃状态 | active() |
适用场景
- 后台任务、队列处理中的自动发帖
- 使用 Laravel Notification 通道进行的通知
- 批处理、定时任务
- 使用应用自身的账号发帖
OAuth (OAuthAgent)
认证流程
Bluesky::withToken()
将通过 Socialite 获取的 OAuthSession 传给 withToken()。
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Session\OAuthSession;
// 从 Laravel session 中恢复(Web 请求)
$session = OAuthSession::create(session('bluesky_session'));
$timeline = Bluesky::withToken($session)->getTimeline();
在后台任务或 Console 中,也可以用保存在数据库里的值组装 OAuthSession。
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Session\OAuthSession;
$session = OAuthSession::create([
'did' => $user->did,
'refresh_token' => $user->refresh_token,
// 对于非 bsky.social 的账号,还需要指定 iss
// 'iss' => $user->iss,
]);
$response = Bluesky::withToken($session)
->refreshSession()
->post('Hello from OAuth');
OAuthSession 的主要键
| 键 | 内容 | 方法 |
|---|
access_token | access token | token() |
refresh_token | refresh token(只能使用一次) | refresh() |
did / sub | Bluesky DID | did() |
iss | 授权服务器 URL | issuer() |
profile.handle | handle | handle() |
profile.displayName | 显示名 | displayName() |
OAuth 的 refresh_token 只能使用一次。请通过 OAuthSessionUpdated 事件,在 token 更新后一定更新数据库。详情请参考 Socialite。
适用场景
- 通过 Socialite 实现用户登录
- 代表用户调用 API
- 需要针对每个用户使用不同账号进行操作的场景
认证之后的 API 调用是通用的
无论使用哪种认证方式,withToken() 之后使用的都是相同的 API 方法。
use Revolution\Bluesky\Facades\Bluesky;
use Revolution\Bluesky\Session\LegacySession;
use Revolution\Bluesky\Session\OAuthSession;
// App Password
Bluesky::login(config('bluesky.identifier'), config('bluesky.password'));
// 或者 OAuth
$session = OAuthSession::create(session('bluesky_session'));
Bluesky::withToken($session);
// ↓ 之后的 API 调用完全相同 ↓
Bluesky::post('Hello Bluesky');
Bluesky::getTimeline();
Bluesky::getProfile();
Bluesky::searchPosts(q: '#laravel');
BlueskyManager 在内部会根据情况使用 LegacyAgent 或 OAuthAgent,但对调用方代码没有影响。
应该选哪种?
| 场景 | 推荐 |
|---|
| 自动发帖、通知、批处理 | App Password |
| 用户登录功能 | OAuth |
| 只做后台任务 | App Password |
| 需要代表用户操作 | OAuth |
| 优先考虑运营简单 | App Password |
| 重视安全性与权限控制 | OAuth |
纠结时,按目的划分最直观。“应用自己动作”就用 App Password,“用户来操作”就用 OAuth。两者也可以组合使用,比如通知用 App Password、用户登录用 OAuth 是常见的组合。
参考链接