Laravel在第三方QQ登陆后的逻辑处理
源码详见:https://gitee.com/liuzhenqing/laravel-bbs
如果直接看到了本篇文章先看一下前面的一篇文章https://blog.csdn.net/qq_25615395/article/details/80251455
现在没有完成的就是当用户使用qq登陆的时候应该强制移步到修改个人资料的页面,因为还没有开发,以后完善
1. 给用户的表添加qq的字段。写在数据库迁移文件中database/migrations/20xx_xx_xx_xxxxxx_add_outh_field_to_users_table.php
在现在是为了将
github
的登陆功能添加进来,也把github需要添加的字段写进来
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddOuthFieldToUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->integer('github_id')->nullable();
$table->string('github_name')->nullable();
$table->string('github_url')->nullable();
$table->string('qq_openid')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->integer('github_id')->nullable();
$table->string('github_name')->nullable();
$table->string('github_url')->nullable();
$table->string('qq_openid')->nullable();
});
}
}
2. 重写第三方服务的提供者
在App\Providers
利用命令php artsian make:provider OAuthServiceProvider
创建OAuthServiceProvider.php
在上一章节的添加在事件监听器中的QQ登陆处理给取消掉
又因为采用的是自定义的服务,因此注入容器中服务提供者在app.php可以去除掉
<?php
namespace App\Providers;
use App\Base\OAuth\QQProvider;
use Illuminate\Support\ServiceProvider;
class OAuthServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
$this->app->make('Laravel\Socialite\Contracts\Factory')->extend('qq', function ($app) {
$config = $app['config']['services.qq'];
return new QQProvider(
$app['request'],
$config['client_id'],
$config['client_secret'],
$config['redirect']
);
});
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
//
}
}
3. 创建QQ服务的提供者,位置我是写在了app\Base\OAuth\QQProvider.php
<?php
namespace App\Base\OAuth;
use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\ProviderInterface;
use Laravel\Socialite\Two\User;
class QQProvider extends AbstractProvider implements ProviderInterface
{
/**
* @var string
*/
private $openId;
protected $scopes = ['get_user_info'];
protected function getTokenUrl()
{
return 'https://graph.qq.com/oauth2.0/token';
}
protected function mapUserToObject(array $user)
{
return (new User())->setRaw($user)->map([
'id' => $this->openId,
'nickname' => $user['nickname'],
'name' => null,
'email' => null,
'avatar' => $user['figureurl_qq_2'],
'gender' => $user['gender']
]);
}
/**
* {@inheritdoc}.
*
* @see \Laravel\Socialite\Two\AbstractProvider::getTokenFields()
*/
protected function getTokenFields($code)
{
return array_merge(parent::getTokenFields($code), [
'grant_type' => 'authorization_code',
]);
}
/**
* {@inheritdoc}.
*
* @see \Laravel\Socialite\Two\AbstractProvider::getAccessToken()
*/
public function getAccessTokenResponse($code)
{
$response = $this->getHttpClient()->get($this->getTokenUrl(), [
'query' => $this->getTokenFields($code),
]);
$content = $response->getBody()->getContents();
parse_str($content, $result);
return $result;
}
protected function getUserByToken($token)
{
$response = $this->getHttpClient()->get('https://graph.qq.com/oauth2.0/me?access_token='.$token);
$this->openId = json_decode($this->removeCallback($response->getBody()->getContents()), true)['openid'];
$response = $this->getHttpClient()->get(
"https://graph.qq.com/user/get_user_info?access_token=$token&openid={$this->openId}&oauth_consumer_key={$this->clientId}"
);
$res = json_decode($this->removeCallback($response->getBody()->getContents()), true);
return $res;
}
protected function getAuthUrl($state)
{
return $this->buildAuthUrlFromBase('https://graph.qq.com/oauth2.0/authorize', $state);
}
/**
* @param mixed $response
*
* @return string
*/
protected function removeCallback($response)
{
if (strpos($response, 'callback') !== false) {
$lpos = strpos($response, '(');
$rpos = strrpos($response, ')');
$response = substr($response, $lpos + 1, $rpos - $lpos - 1);
}
return $response;
}
}
4. 下面就是最重要的登陆之后的逻辑处理了—控制器App\Http\Controllers\Auth\SocialiteLoginController.php
/**
* 处理第三方登录的回调
*
* @param $service
*/
public function handleProviderCallback($service)
{
$user = Socialite::driver($service)->user();
$manager = new OAuthManager($service);
$manager->auth($user);
return redirect('/');
// dd($user);
}
4. 下面就是最重要的登陆之后的逻辑处理了—第三方登陆处理中心app\Base\OAuth\OAuthManager.php
这里也将
github
的登陆处理给贴出来了,具体的可以根据需要修改
也许我这里的用户表跟你的不一样,请酌情修改就行了
<?php
namespace App\Base\OAuth;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
class OAuthManager
{
protected $driver;
public function __construct($driver)
{
$this->driver = $driver;
}
public function auth($user){
$method = 'authWith'.ucfirst($this->driver);
if (! method_exists($this,$method)){
return false;
}
return $this->$method($user);
}
protected function authWithQq($user){
// 如果已经存在 -> 登录
$current_user = User::where('qq_openid',$user->id)->first();
if ($current_user){
Auth::login($current_user);
return $current_user;
}
// 创建用户
// 判断有重复昵称则拼接随机字符串
$username = $user->nickname;
// 如果的qq好的邮箱为空的
if($user->email == null){
}
if (User::query()->where('name',$user->nickname)->first()){
$username = $username.'_'.str_random(5);
}
$current_user = User::create([
'qq_openid' =>$user->id,
'name' => $username,
'email' => $user->email,
'is_active' => 1,
'avatar' => $user->avatar,
'password' => '',
'confirmation_token' => str_random(40),
]);
Auth::login($current_user);
return $current_user;
}
// 存储github用户信息
protected function authWithGithub($user){
// 如果已经存在 -> 登录
$current_user = User::where('github_id',$user->id)->first();
if ($current_user){
Auth::login($current_user);
return $current_user;
}
$username = $user->nickname;
if (User::query()->where('name',$user->nickname)->first()){
$username = $username.'_'.str_random(5);
}
// 创建用户
$current_user = User::create([
'name' => $username,
'email' => $user->email,
'activated' => 1,
'avatar' => $user->avatar,
'github_id' => $user->id,
'github_name' => $user->name,
'github_url' => $user->user['url'],
'password' => ''
]);
$current_user->activated = true;
$current_user->save();
Auth::login($current_user);
return $current_user;
}
}