下一步是向 Web 控制器中添加 yii\authclient\AuthAction,然后实现 successCallback
方法,
该方法与你的实际需要保持一致。典型的最终控制器类似如下代码:
class SiteController extends Controller
{
public function actions()
{
return [
'auth' => [
'class' => 'yii\authclient\AuthAction',
'successCallback' => [$this, 'onAuthSuccess'],
],
];
}
public function onAuthSuccess($client)
{
$attributes = $client->getUserAttributes();
/* @var $auth Auth */
$auth = Auth::find()->where([
'source' => $client->getId(),
'source_id' => $attributes['id'],
])->one();
if (Yii::$app->user->isGuest) {
if ($auth) { // 登录
$user = $auth->user;
Yii::$app->user->login($user);
} else { // 注册
if (isset($attributes['email']) && User::find()->where(['email' => $attributes['email']])->exists()) {
Yii::$app->getSession()->setFlash('error', [
Yii::t('app', "User with the same email as in {client} account already exists but isn't linked to it. Login using email first to link it.", ['client' => $client->getTitle()]),
]);
} else {
$password = Yii::$app->security->generateRandomString(6);
$user = new User([
'username' => $attributes['login'],
'email' => $attributes['email'],
'password' => $password,
]);
$user->generateAuthKey();
$user->generatePasswordResetToken();
$transaction = $user->getDb()->beginTransaction();
if ($user->save()) {
$auth = new Auth([
'user_id' => $user->id,
'source' => $client->getId(),
'source_id' => (string)$attributes['id'],
]);
if ($auth->save()) {
$transaction->commit();
Yii::$app->user->login($user);
} else {
print_r($auth->getErrors());
}
} else {
print_r($user->getErrors());
}
}
}
} else { // 用户已经登陆
if (!$auth) { // 添加验证提供商(向验证表中添加记录)
$auth = new Auth([
'user_id' => Yii::$app->user->id,
'source' => $client->getId(),
'source_id' => $attributes['id'],
]);
$auth->save();
}
}
}
}
当用户由外部服务验证通过后调用 successCallback
方法。通过 $client
实例我们可以检索收到的信息。
在我们的例子中,我们可以:
注意:不同的验证客户端在验证通过时可能需要不同的方法。例如:Twitter 不返回用户电子邮件, 所以你需要单独处理此种情况。
尽管每个客户端不尽相同,但它们都共享同一个基础接口 yii\authclient\ClientInterface, 该接口包含了通用的 API。
每个客户端都有一些描述性的数据,分别用于不同的目的:
id
- 唯一客户 ID,用于与其它客户端区分,它可以用于 URL 和日志等。name
- 外部验证提供商名称,与该客户端匹配。不同的客户端可以使用相同的名称,
即它们指的是同一个外部验证提供商。
例如:谷歌 OpenID 客户端和 Google OAuth 客户端有一个相同的名称 “google”。
该树形可以用在数据库内部、CSS 样式中等等。title
- 用户友好的外部验证提供商名称,用于在验证客户端的视图层展示。每个验证客户端都有不同的验证流程,但是它们都支持 getUserAttributes()
方法,
可在验证通过后调用。
该方法允许你获取外部用户账户的信息,如 ID、电子邮件账户、全名、首选语言等等。 注意:对于每个提供商,可用域的名称和存在性可能不同。
定义属性列表,用于通知外部验证提供商应当返回列表,根据不同的客户端类型:
requiredAttributes
和 optionalAttributes
.scope
域。注意,
不同的提供商对于范围的格式定义可能不同。提示:如果你正在使用若干个不同的客户端,你可以使用 yii\authclient\BaseClient::$normalizeUserAttributeMap 统一返回属性的列表。
yii\authclient\OAuth1 和 yii\authclient\OAuth2 均提供了 api()
方法,
可以用于访问外部服务提供商的 REST API。然而该方法比较基础,可能并不足以访问
所有外部 API 功能。该方法主要用于取回外部用户账户数据。
要使用 API 调用,你需要根据 API 说明设置 yii\authclient\BaseOAuth::$apiBaseUrl。 之后就可以调用 yii\authclient\BaseOAuth::api() 方法了:
use yii\authclient\OAuth2;
$client = new OAuth2;
// ...
$client->apiBaseUrl = 'https://www.googleapis.com/oauth2/v1';
$userInfo = $client->api('userinfo', 'GET');
yii\authclient\widgets\AuthChoice 小部件用于视图中:
<?= yii\authclient\widgets\AuthChoice::widget([
'baseAuthUrl' => ['site/auth'],
'popupMode' => false,
]) ?>