前言

其实第三方账号登陆已经是一个老生常谈的问题了,网上的解决方案也有很多,比如适配器模式,桥接模式等等。
个人laravel使用的auth包,是passport,里面可以自定义authguardprovider等等。
就可以为passport添加各种第三方登陆的功能。

相关文档:laravel/passport

实现

其实实现也非常简单,对应的 guardprovider 都是可以自定义的。
而且 对应的自定义 provider 只需要 实现对应的 UserProviderInterface 接口即可。
IRS 为例,我们可以自定义一个 IrsUserProvider 类,实现 UserProviderInterface 接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php

namespace App\Passport;

use App\Handlers\IRSUserHandler;
use App\Handlers\IRSV2UserHandler;
use App\Models\User;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;
use Psr\Http\Message\ServerRequestInterface;
use Sk\Passport\UserProvider;

class IRSV2UserProvider extends UserProvider
{
public function validate(ServerRequestInterface $request)
{
$this->validateRequest($request, [
'token' => 'required|string',
]);
}

public function retrieve(ServerRequestInterface $request)
{
$inputs = $this->only($request, [
'token',
]);
try {
[$user, $info] = IRSV2UserHandler::verify($inputs['token']);
} catch (\Exception | GuzzleException $exception) {
return yzz_response_error('IRS-V2 用户验证失败', 401);
}
return $user;
}

}

然后在 config/auth.php 中添加对应的 passport->clients->irs-v2 配置。

1
2
3
4
5
6
7
8
'passport' => [
'clients' => [
'irs-v2' => [
'id' => env('PASSPORT_IRS_CLIENT_ID'),
'secret' => env('PASSPORT_IRS_CLIENT_SECRET')
],
]
]

然后在 config/passportgrant.php 中添加对应的 grant 配置。

1
2
3
'grant' => [
'irs-v2-social' => \App\Passport\IRSV2UserProvider::class,
]

最后在控制器里面使用 passportauth 方法即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    public function storeByIRSV2(ServerRequestInterface $request): mixed
{
$parsedBody = $request->getParsedBody();
$ticket = $parsedBody['ticketId'];
$appId = $parsedBody['appId'];
try {
$accessToken = $this->getAccessToken($ticket, $appId);
} catch (AuthenticationException $e) {
throw $e;
}
try {
// $accessToken = "0d53b4f6ece242f2b0be91352a124c71";
$request = $request->withParsedBody(array(
'token' => $accessToken,
'grant_type' => 'irs-v2-social',
'client_id' => config('auth.passport.clients.irs-v2.id'),
'client_secret' => config('auth.passport.clients.irs-v2.secret'),
));
$response = json_decode($this->issueToken($request)->content(), true);
return response_success('OK',$response);


} catch (\Exception $exception) {
return $exception->getMessage();
}
}