docs/src/6.x/oauth.md
OAuth 是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是 2.0 版。
摘自:RFC 6749
步骤解释:
(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。
关于 OAuth 协议我们就简单了解到这里,如果还有不熟悉的同学,请 Google 相关资料
在微信里的 OAuth 其实有两种:公众平台网页授权获取用户信息、开放平台网页登录。
它们的区别有两处,授权地址不同,scope 不同。
- 公众平台网页授权获取用户信息
授权 URL: https://open.weixin.qq.com/connect/oauth2/authorize
Scopes: snsapi_base 与 snsapi_userinfo
- 开放平台网页登录
授权 URL: https://open.weixin.qq.com/connect/qrconnect
Scopes: snsapi_login
他们的逻辑都一样:
/user/profilescope 为 snsapi_base 时不显示)callback.php 并带上 code: ?code=CODE&state=STATE。callback.php 中得到 code 后,通过 code 再次向微信服务器请求得到 网页授权 access_token 与 openidopenid 去请求 API 得到用户信息(可选)intend_url 页面(/user/profile)。看懵了?没事,使用 SDK,你不用管这么多。:smile:
注意,上面的第 3 步:redirect_uri=callback.php 实际上我们会在
callback.php后面还会带上授权目标页面user/profile,所以完整的redirect_uri应该是下面的这样的 PHP 去拼出来:'redirect_uri='.urlencode('callback.php?target=user/profile')结果:redirect_uri=callback.php%3Ftarget%3Duser%2Fprofile
从上面我们所描述的授权流程来看,我们至少有 3 个页面:
在开始之前请一定要记住,先登录公众号后台,找到边栏 “开发” 模块下的 “接口权限”,点击 “网页授权获取用户基本信息” 后面的修改,添加你的网页授权域名。
如果你的授权地址为:
http://www.abc.com/xxxxx,那么请填写www.abc.com,也就是说请填写与网址匹配的域名,前者如果填写abc.com是通过不了的。
$redirectUrl = $oauth->scopes(['snsapi_userinfo'])->redirect();
// 指定回调 URL,比如设置回调 URL 为当前页面
$redirectUrl = $oauth->scopes(['snsapi_userinfo'])->redirect($request->fullUrl());
返回值 $redirectUrl 是一个字符串 URL,请自行使用框架的跳转方法实现跳转,PHP 原生写法:
header("Location: {$redirectUrl}");
在 Laravel 框架中控制器方法是要求返回响应值:
return \redirect($redirectUrl);
$code = "微信回调URL携带的 code"; // $_GET['code']
$user = $oauth->userFromCode($code);
返回的 $user 是 Overtrue\Socialite\User 对象,你可以从该对象拿到更多的信息。
$user 可以用的方法
$user->getId(); 对应微信的 openid$user->getNickname(); 对应微信的 nickname$user->getName(); 对应微信的 nickname$user->getAvatar(); 头像地址$user->getRaw(); 原始 API 返回的结果$user->getAccessToken(); access_token$user->getRefreshToken(); refresh_token$user->getExpiresIn(); expires_in,Access Token 过期时间$user->getTokenResponse(); 返回 access_token 时的响应值
$user里没有openid,$user->id便是openid. 如果你想拿微信返回给你的原样的全部信息,请使用:$user->getRaw();
当 scope 为 snsapi_base 时 $oauth->userFromCode($code); 对象里只有 id,没有其它信息。
我们这里来用公众号原生 PHP 写法举个例子,oauth_callback 是我们的授权回调 URL (未 urlencode 编码的 URL), user/profile 是我们需要授权才能访问的页面,它的 PHP 代码如下:
// http://easywechat.com/user/profile
<?php
use EasyWeChat\OfficialAccount\Application;
$config = [
'app_id' => 'wx3cf0f39249eb0exx',
'secret' => 'f1c242f4f28f735d4687abb469072axx',
'token' => 'easywechat',
'aes_key' => '......'
//...
];
$app = new Application($config);
$oauth = $app->getOauth();
// 未登录
//callback_url 是授权回调的URL
if (empty($_SESSION['wechat_user'])) {
$_SESSION['intend_url'] = 'user/profile';
//生成完整的授权URL
$redirectUrl = $oauth->redirect('callback_url');
header("Location: {$redirectUrl}");
exit;
} else {
// 已经登录过,则从 session 中取授权者信息
$user = $_SESSION['wechat_user'];
// ...
}
授权回调页
用户授权完成后浏览器调回的 URL 逻辑:
// http://easywechat.com/oauth_callback
<?php
use EasyWeChat\OfficialAccount\Application;
$config = [
'app_id' => 'wx3cf0f39249eb0exx',
'secret' => 'f1c242f4f28f735d4687abb469072axx',
'token' => 'easywechat',
'aes_key' => '......'
//...
];
$app = new Application($config);
$oauth = $app->getOauth();
// 获取 OAuth 授权用户信息
$user = $oauth->userFromCode($_GET['code']);
$_SESSION['wechat_user'] = $user->toArray();
$targetUrl = empty($_SESSION['intend_url']) ? '/' : $_SESSION['intend_url'];
header('Location:'. $targetUrl); // 跳转回授权前的目标页面:user/profile
上面的例子呢都是基于 $_SESSION 来保持会话的,在微信客户端中,你也可以结合 Cookies 来存储,但是有效期平台不一样时间也不一样,好像 Android 的失效会快一些,不过基本也够用了。