Laravel + Vue.js 的 SPA 项目中进行微信网页授权的一种姿势

相信 Laravel 和 Vue.js 很多人都已经相当熟悉了,在较近版本的 Laravel 中,已经默认支持 Vue 组件化开发,这也顺应了眼下基于 API 前后分离以及开发单页面应用(SPA)的均势。

项目基本情况

  • Laravel 5.4
  • overtrue/laravel-wechat 包 (内部依赖 overtrue/wechat)
  • vue.js 2.x
  • vue-router (非必须)
  • vue-axios (非必须)

解决步骤

  1. 安装 laravel-wechat

使用 composer 安装好 laravel-wechat 包并做好相关配置,具体如下:

  • 在 config\app.php 中的 providers 数组下加入下面两行
Overtrue\LaravelWechat\ServiceProvider::class,
Overtrue\LaravelSocialite\ServiceProvider::class,
  • 在 app\Http\Kernel.php 中的 $routeMilleware 下加入
'wechat.oauth' => \Overtrue\LaravelWechat\Middleware\OAuthAuthenticate::class,

其它一些微信公众号相关的参数配置请参考 EasyWechat 官方文档

  1. 添加路由

在 routes\web.php 中新增一条路由如下:

Route::get('/mobile', 'MobileController@index')->middleware('wechat:oauth');

注意该路由使用了 oauth:wechat 中间件,这个中间件将实现网页授权逻辑。

  1. 创建控制器及声明方法

创建一个控制器 MobileController,并在其中声明如下方法:

public function index()
{
    // 拿到授权微信用户资料
    $wechatUser = session('wechat.oauth_user');

    return response()->view('mobile')->cookie('openid', $wechatUser->id ?? null);
}

这一方法将会在 http 响应中带上一个含有 openid 值的 Cookie,需要注意的是,这个 Cookie 是加密了的,所以不用担心安全性方面的问题。如果不想加密,可以在 EncryptCookies 中间件里进行配置。

此外,除了直接使用 openid 之外,也可以使用其它值,甚至根据 openid 查到你本地数据库中的用户数据,进而在 Cookie 中传 user_id。具体用法依个人喜好和需求而定。

响应头中加入 Cookie 也是所有步骤中的关键所在,有了这个 Cookie,后续前端页面向服务器发起请求时会自动带上这个 Cookie。

  1. 添加模板以及 Vue 组件,这个可以参照 Laravel 默认的 welcome.blade.php 模板以及 App.vue 组件调整得到。(注意模板文档名,按前面示例,应该改成 mobile.blade.php)

  2. 定义 API 路由及对应的控制器,在前端页面里根据需要向服务器发起请求。具体怎么发就得看用的什么插件了,比如我用的 axios,事件就很简单

axios.get(url).then(response => {
  console.log(response.data)
}).catch(error => {
  console.log(error)
})
  1. 最后,在 API 控制器里,可以取到当前授权的微信用户 openid
// 请求头里的 openid
$openid = Crypt::decrypt(\Request::cookie('openid'));

这里使用 Crypt::decrypt() 方法进行解密,如果没加密,可不使用。

总结

由可可见,在 SPA 项目里完成网页授权也十分容易,当然,这也部分归功于超哥的 laravel-wechat 包。

因为不同于传统的 Laravel 项目,前后分离的 SPA 项目前后端以 API 作为纽带,而在这些 API 相关的控制器里,无法再随意使用服务器会话,所以这里使用 http cookie 作为替代,实际上网页授权逻辑,在进入 SPA 页面 Vue 根实例创建之前就已经完成了,算是一种变通吧,至于这个姿势科学、优雅与否,我也不太好说,但至少目前为止自己的几个项目中使用一切正常…… :smile:

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由 Summer 于 6年前 加精
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 11

直接在API控制器里拿session('wechat.oauth_user')岂不更方便~

6年前 评论

@史沟飞 API 路由都没使用 web 中间件组,相应的控制器里能使用 session? 至少我试过不行……

6年前 评论

@田勇 大佬,最近我也在使用laravel+vue来做基于微信公众号的应用,找遍全网基本都是说结合用jwt-auth来实现的,一直也很懵逼,使用easy-wechat很方便,但是结合vue来弄的没搜到相关的实例,不知道是不是我搜索姿势不对。

搜到您这篇文章终于豁然开朗,直接使用cookie函数来将用户openid返回给前端,前端通过携带openid去api请求该用户的相关数据,不知道我理解正确不正确,还有就是您这篇文章2年前发的,不知道您现在是否还在使用这个方案来实现,这个方案是否存在其它问题,还望大佬赐教

4年前 评论

@MaNiu 理解没错!网页授权的套路一直没变,虽然两年了,但这思路应该仍然适用,你可以自己试下。

4年前 评论

好的,感谢大佬指点

4年前 评论

@田勇 另外还求教下大佬,这个方案不需要结合jwt-auth之类的api鉴权吗?

4年前 评论

@MaNiu 微信网页授权实际就是 oauth,已经比较成熟了,而且 laravel 的 cookie 加密了,还是安全的。它的实质相当于“登录”,知道当前用户对应你数据库里哪个用户(与输入用户名密码来判断的性质差不多)。至于 jwt 是你登录之后根据用户生成 TOKEN 用来 API 鉴权的,两者一般是配合使用。

4年前 评论

大佬,求教下,使用
return response()->view('mobile')->cookie('openid', $wechatUser->id ?? null);
存储在前端的值,在前端使用js读取不到是什么原因啊

4年前 评论

@MaNiu 这些 Cookie 是服务端设置的,客户端不能访问,不过客户端以后的请求头中都会带上这个 cookie。

4年前 评论

@田勇 大佬,这个问题我已经解决了,是因为laravel返回的cookies设了http only为true,所以客户端没法取到cookies值,将http only属性改为false就可以了;我现在使用你这种设置cookies的方法稍微改动了下,在微信授权后将该用户信息写进数据库创建该用户本地账户,将该用户信息生成token使用cookies设置到前端,前端获取cookies信息中的token放到header里通过api去请求数据,这样就可以在路由里使用api.auth来做权限认证并获取数据了,不知道我这种搞法是否合理,还望大佬指教

下面是核心代码:

将生成的token返回设置给前端

return response()->view('index')->cookie('TOKEN', $this->getToken(), 999999999, null, null, false, false);

中间件验证权限


Route::middleware('api.auth')->prefix('v1')->name('api.v1.')->namespace('Api')->group(function () {
...
});
4年前 评论

最近一个前后端分离的项目刚刚用到jwt-auth + 微信网页授权,也记录在github上了,希望能帮助正在使用的新手们。 jwt-auth + 微信网页授权👇

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!