网页授权

    步骤解释:

    关于 OAuth 协议我们就简单了解到这里,如果还有不熟悉的同学,请 Google 相关资料

    微信 OAuth

    在微信里的 OAuth 其实有两种:公众平台网页授权获取用户信息、。

    它们的区别有两处,授权地址不同, 不同。

    1. 用户尝试访问一个我们的业务页面,例如: /user/profile
    2. 如果用户已经登录,则正常显示该页面
    3. 系统检查当前访问的用户并未登录(从 session 或者其它方式检查),则跳转到跳转到微信授权服务器(上面的两种中一种授权 URL ),并告知微信授权服务器我的回调URL(redirect_uri=callback.php),此时用户看到蓝色的授权确认页面(scopesnsapi_base 时不显示)
    4. 用户点击确定完成授权,浏览器跳转到回调URL: callback.php 并带上 code?code=CODE&state=STATE
    5. callback.php 中得到 code 后,通过 code 再次向微信服务器请求得到 网页授权 access_tokenopenid
    6. 你可以选择拿 openid 去请求 API 得到用户信息(可选)
    7. 将用户信息写入 SESSION。
    8. 跳转到第 3 步写入的 target_url 页面(/user/profile)。

    从上面我们所描述的授权流程来看,我们至少有3个页面:

    1. 业务页面,也就是需要授权才能访问的页面。
    2. 发起授权页,此页面其实可以省略,可以做成一个中间件,全局检查未登录就发起授权。
    3. 授权回调页,接收用户授权后的状态,并获取用户信息,写入用户会话状态(SESSION)。

    开始之前

    在开始之前请一定要记住,先登录公众号后台,找到边栏 “开发” 模块下的 “接口权限”,点击 “网页授权获取用户基本信息” 后面的修改,添加你的网页授权域名。

    在 SDK 中,我们使用名称为 oauth 的模块来完成授权服务,我们主要用到以下两个 API:

    1. $response = $app->oauth->scopes(['snsapi_userinfo'])
    2. ->redirect();

    当你的应用是分布式架构且没有会话保持的情况下,你需要自行设置请求对象以实现会话共享。比如在 框架中支持Session储存在Redis中,那么需要这样:

    1. $response = $app->oauth->scopes(['snsapi_userinfo'])
    2. ->setRequest($request)
    3. ->redirect();
    4. //回调后获取user时也要设置$request对象

    当然你也可以在发起授权的时候指定回调URL,比如设置回调URL为当前页面:

    你可以选择在框架中做一些正确的响应,比如在 Laravel 框架中控制器方法是要求返回响应值的,那么你就直接:

    1. return $response;

    在有的框架 (比如yii2) 中是直接 echo 或者 $this->display() 这种的时候,你就直接:

    1. $response->send(); // Laravel 里请使用:return $response;

    获取已授权用户

    返回的 $userOvertrue\Socialite\User 对象,你可以从该对象拿到。

    scopesnsapi_base$oauth->user(); 对象里只有 id,没有其它信息。

    网页授权实例

    我们这里来用原生 PHP 写法举个例子,oauth_callback 是我们的授权回调URL (未urlencode编码的URL), user/profile 是我们需要授权才能访问的页面,它的 PHP 代码如下:

    1. // http://easywechat.org/user/profile
    2. <?php
    3. use EasyWeChat\Factory;
    4. $config = [
    5. // ...
    6. 'oauth' => [
    7. 'scopes' => ['snsapi_userinfo'],
    8. 'callback' => '/oauth_callback',
    9. ],
    10. // ..
    11. ];
    12. $app = Factory::officialAccount($config);
    13. $oauth = $app->oauth;
    14. if (empty($_SESSION['wechat_user'])) {
    15. $_SESSION['target_url'] = 'user/profile';
    16. // 这里不一定是return,如果你的框架action不是返回内容的话你就得使用
    17. // $oauth->redirect()->send();
    18. }
    19. // 已经登录过
    20. $user = $_SESSION['wechat_user'];
    21. // ...

    授权回调页:

    1. // http://easywechat.org/oauth_callback
    2. <?php
    3. use EasyWeChat\Factory;
    4. $config = [
    5. // ...
    6. ];
    7. $app = Factory::officialAccount($config);
    8. $oauth = $app->oauth;
    9. // 获取 OAuth 授权结果用户信息
    10. $user = $oauth->user();
    11. $_SESSION['wechat_user'] = $user->toArray();
    12. $targetUrl = empty($_SESSION['target_url']) ? '/' : $_SESSION['target_url'];
    13. header('location:'. $targetUrl); // 跳转到 user/profile

    上面的例子呢都是基于 来保持会话的,在微信客户端中,你可以结合 COOKIE 来存储,但是有效期平台不一样时间也不一样,好像 Android 的失效会快一些,不过基本也够用了。