返回介绍

网页授权

发布于 2021-04-03 04:02:28 字数 16691 浏览 2422 评论 0 收藏 0

关于 OAuth2.0

OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。

摘自:RFC 6749

步骤解释:

(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。

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

微信 OAuth

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

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

  • 公众平台网页授权获取用户信息 授权 URL: https://open.weixin.qq.com/connect/oauth2/authorize Scopes: snsapi_basesnsapi_userinfo

  • 开放平台网页登录 授权 URL: https://open.weixin.qq.com/connect/qrconnect Scopes: snsapi_login

他们的逻辑都一样:

  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)。

{warning} 看懵了?没事,使用 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个页面:

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

开始之前

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

如果你的授权地址为:http://www.abc.com/xxxxx,那么请填写 www.abc.com,也就是说请填写与网址匹配的域名,前者如果填写 abc.com 是通过不了的。

SDK 中 OAuth 模块的 API

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

发起授权

// $redirectUrl 为跳转目标,请自行 302 跳转到目标地址
$redirectUrl = $app->oauth->scopes(['snsapi_userinfo'])
                          ->redirect();

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

$redirectUrl = $app->oauth->scopes(['snsapi_userinfo'])
                          ->redirect($request->fullUrl());

它的返回值 $redirectUrl 是一个字符串跳转地址,请自行使用框架的跳转方法实现跳转,PHP 原生写法:

header("Location: {$redirectUrl}");

Laravel 框架中控制器方法是要求返回响应值的,那么你就直接:

return \redirect($redirectUrl);

获取已授权用户

$code = "微信回调URL携带的 code";

$user = $app->oauth->userFromCode($code);

返回的 $userOvertrue\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 时的响应值

{warning} 注意:$user 里没有 openid$user->id 便是 openid. 如果你想拿微信返回给你的原样的全部信息,请使用:$user->getRaw();

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

网页授权实例

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

// http://easywechat.org/user/profile
<?php

use EasyWeChat\Factory;

$config = [
  // ...
  'oauth' => [
      'scopes'   => ['snsapi_userinfo'],
      'callback' => '/oauth_callback',
  ],
  // ..
];

$app = Factory::officialAccount($config);
$oauth = $app->oauth;

// 未登录
if (empty($_SESSION['wechat_user'])) {

  $_SESSION['target_url'] = 'user/profile';

  $redirectUrl = $oauth->redirect();

  header("Location: {$redirectUrl}");
  exit;
}

// 已经登录过
$user = $_SESSION['wechat_user'];

// ...

授权回调页:

// http://easywechat.org/oauth_callback
<?php

use EasyWeChat\Factory;

$config = [
  // ...
];

$app = Factory::officialAccount($config);
$oauth = $app->oauth;

// 获取 OAuth 授权结果用户信息
$code = "微信回调URL携带的 code";
$user = $oauth->userFromCode();

$_SESSION['wechat_user'] = $user->toArray();

$targetUrl = empty($_SESSION['target_url']) ? '/' : $_SESSION['target_url'];

header('Location:'. $targetUrl); // 跳转到 user/profile

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

参考阅读

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文