JeffreyBool
阅读 473
测试

安装 socialiteproviders

socialiteproviders 为 Laravel Socialite 提供了更多的第三方登录方式,基本上你需要的,都能在这里找到。这个组件方便我们完成整个 OAuth 流程,不过对于我们开发接口来说,只用到了它部分的功能。 首先找到 微信的provider,一步步完成安装。

$ composer require socialiteproviders/weixin

微信登录微信登录

可以省略 ServiceProvider 的设置。

设置 EventServiceProvider

app/Providers/EventServiceProvider.php

 .
 .
 .
    protected $listen = [
        \SocialiteProviders\Manager\SocialiteWasCalled::class => [
            // add your listeners (aka providers) here
            'SocialiteProviders\Weixin\WeixinExtendSocialite@handle'
        ],
        Registered::class => [
            SendEmailVerificationNotification::class,
        ],

        \Illuminate\Auth\Events\Verified::class => [
            \App\Listeners\EmailVerified::class,
        ],
    ];

.
.
.

好了,暂时只需要这两步,我们就能开始使用了。

功能调试

还记得上一章我们提到,客户端可能有两种实现方式, 我们先分别了解一下这两种情况,服务器端该如何处理。

1). 客户端已经获取 access_token

因为客户端已经获取了 access_token,需要将 access_token 发给服务器,服务器通过 access_token 获取用户信息,如果成功的换取了用户信息则说明 access_token 正确,用户微信登录成功。

打开 tinker 开始调试

$ php artisan tinker

我们上一章已经讲解了如何通过 微信开发者工具 获取一个可用的 access_token,现在我们申请一个 access_token,然后在 tinker 中输入如下代码,将 ACCESS_TOKEN 替换为你自己的。

$accessToken = 'ACCESS_TOKEN';
$driver = Socialite::driver('weixin');
$oauthUser = $driver->userFromToken($accessToken);

将以上代码贴到 Tinker 里执行:

filefile

我们看到报错了,这里是因为微信的流程中换取用户信息的接口,需要我们同时提交 access_tokenopenidfile

执行如下代码,替换 OPEN_ID 为你自己的

$accessToken = 'ACCESSTOKEN';
$openID = 'OPENID';
$driver = Socialite::driver('weixin');
$driver->setOpenId($openID);
$oauthUser = $driver->userFromToken($accessToken);

将以上代码贴到 Tinker 里执行:

filefile

请求成功,获取了用户信息

只有微信获取用户信息需要同时使用 access_tokenopenid ,如果你开发的是微博等其他的第三方登录,并不需要 $driver->setOpenId($openID); 这一步。

2). 客户端只获取授权码(code)

这种方式是推荐的安全做法,客户端不保存 app_secret,获取到授权码后就提交给服务器,服务器完成换取 access_token 及换取用户信息的流程。 使用这种方式,首先需要在服务端配置 app_idapp_secret,修改如下

config/services.php

.
.
.
	'weixin' => [
		'clientid' => env('WEIXINKEY'),
		'clientsecret' => env('WEIXINSECRET'),
		'redirect' => env('WEIXINREDIRECTURI'),  
	], 
.
.
.

.env

.
.
.
# socialite weixin
WEIXINKEY=wx353901f6*****
WEIXINSECRET=d4624c36b6795d1d9******

注意将 WEIXIN_KEYWEIXIN_SECRET 替换为你自己的 appIdappsecret

不要忘记修改 .env.example

.
.
.
# socialite weixin
WEIXINKEY=
WEIXINSECRET=

打开 tinker

$ php artisan tinker

通过 微信开发者工具 获取一个 code,执行如下代码,将 CODE 替换成你自己的

$code = 'CODE';
$driver = Socialite::driver('weixin');
$response = $driver->getAccessTokenResponse($code);
$driver->setOpenId($response['openid']);
$oauthUser = $driver->userFromToken($response['access_token']);

将以上代码贴到 Tinker 里执行:

filefile

可以看到,我们通过授权码,成功获取了 access_tokenopenid,然后换取了用户信息。

出于安全的考虑,授权码只能使用一次!!!请不要重复使用同一个 Code 进行调试,如果你调试中报错了,可以打印一下 $responsecode been used, hints 就说明 Code 已经使用过了。

第三方登录处理流程

最终服务器获取了用户在微信的用户信息,这一点很重要,无论使用上面哪种方式,都一定要保证用户数据是服务器自己通过 access_token 获取的,还有这样才能验证客户端提交数据( code 或 access_token )的真实性。获取到的用户数据如下

user: [
   "openid" => "xxxxxxx",
   "nickname" => "xxx",
   "sex" => 1,
   "language" => "zh_CN",
   "city" => "成都",
   "province" => "四川",
   "country" => "中国",
   "headimgurl" => "avatar",
   "privilege" => [],
   "unionid" => "xxxxxx",
 ]

现在两种情况

  1. 用户第一次使用微信登录,根据微信的数据,在 Larabbs 中创建一个用户,返回该用户的登录凭证

  2. 用户已经使用过微信登录,则找到数据库中对应的用户,返回该用户的登录凭证

那么如何来分辨用户是否已存在,就需要一个用户的唯一标识。任何一个第三方平台,返回的用户信息都会有一个唯一标识,socialite 已经为我们封装好了,直接使用 $oauthUser->getId() 即可获取,对于微信来说,这个唯一标识叫做 openid。不过微信还有一个 unionid 的概念,大家可以看一下 这里 的回答。

微信关于unionid的解释

如果开发者拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过 unionid 来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的 unionid 是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid 是相同的。

所以我们的处理如下

  • 根据用户的 openid/unionid 查找数据库中已存在的用户

  • 用户存在,返回该用户的登录凭证

  • 用户不存在,根据微信信息创建用户,返回该用户的登录凭证

提交代码

下一节我们完成代码的开发, 先提交一下代码

$ git add -A
$ git commit -m "add socialiteproviders"
关注下面的标签,发现更多相似文章
评论
相关推荐
11111

111111...

1111

wd...

1111

djsdhsdjhsjhdhjs ddsdsd...

国内知名Wchat团队荣誉出品顶级IM通讯聊天系统

国内知名Wchat团队荣誉出品顶级IM通讯聊天系统 团队言语在先: 想低价购买者勿扰(团队是在国内首屈一指的通信公司离职后组建,低价购买者/代码代码贩子者/同行勿扰/基础版本低于30w勿扰) 。想购买...

test

<div style="margin-top:20px"> <el-tabs v-model="editableTabsValue" tab-...

测试标题

chenyuncaic...

我的测试文章

这里我的标题 非 这里是被信息,我希望得到备注 我的第二个标题...

f'g'h'g'h'f'g'h'g'f'h

发布告白夫妇...

nestjs+vue+ts打造一个酷炫的星空聊天室

简介😛 闲暇时间想做一个聊天室来巩固前端技能,于是在2020年6月24号就开始了阿童木聊天室的开发之旅。😈 项目采用全 typescript 开发,这是为了以后的功能迭代打基础。当然,我本身也是很...

好几个放假

东方红格当然多层次发鬼地方...

《快学 Go 语言》第 16 课 —— 包管理 GOPATH 和 Vendor

来源: 知乎 原文: 《快学 Go 语言》第 16 课 —— 包管理 GOPATH 和 Vendor 到目前位置我们一直在编写单文件代码,只有一个 main.go 文件。本节我们要开始朝完整的项目结构...

dddd

...

《快学 Go 语言》第 15 课 —— 反射

来源: 知乎 原文: 《快学 Go 语言》第 15 课 —— 反射 反射是 Go 语言学习的一个难点,但也是非常重要的一个知识点。反射是洞悉 Go 语言类型系统设计的法宝,Go 语言的 ORM 库离不...

hello

*《快学 Go 语言》第 14 课 —— 魔术变性指针来源: 知乎 原文: 《快学 Go 语言》第 14 课 —— 魔术变性指针 本节我们要学习一些 Go 语言的魔法功能,通过内置的 unsafe 包...

《快学 Go 语言》第 14 课 —— 魔术变性指针

来源: 知乎 原文: 《快学 Go 语言》第 14 课 —— 魔术变性指针 本节我们要学习一些 Go 语言的魔法功能,通过内置的 unsafe 包提供的功能,直接操纵指定内存地址的内存。有了 unsa...

《快学 Go 语言》第 13 课 —— 并发与安全

来源: 知乎 原文: 《快学 Go 语言》第 13 课 —— 并发与安全 上一节我们提到并发编程不同的协程共享数据的方式除了通道之外还有就是共享变量。虽然 Go 语言官方推荐使用通道的方式来共享数据,...

《快学 Go 语言》第 12 课 —— 通道

来源: 知乎 原文: 《快学 Go 语言》第 12 课 —— 通道 不同的并行协程之间交流的方式有两种,一种是通过共享变量,另一种是通过队列。Go 语言鼓励使用队列的形式来交流,它单独为协程之间的队列...

《快学 Go 语言》第 11 课 —— 千军万马跑协程

来源: 知乎 原文: 《快学 Go 语言》第 11 课 —— 千军万马跑协程 协程和通道是 Go 语言作为并发编程语言最为重要的特色之一,初学者可以完全将协程理解为线程,但是用起来比线程更加简单,占用...

测试发布

测试文章发布...

《快学 Go 语言》第 10 课 —— 错误与异常

来源: 知乎 原文: 《快学 Go 语言》第 10 课 —— 错误与异常 Go 语言的异常处理语法绝对是独树一帜,在我见过的诸多高级语言中,Go 语言的错误处理形式就是一朵奇葩。一方面它鼓励你使用 C...