Laravel 5.5 发布,ThinkSNS+ 升级以及状况分享。
哈哈,自从 ThinkSNS+ 开始使用 Laravel 重新开发后,一直坚持在 Laravel China 写 Laravel 在 ThinkSNS+ 应用中的一些新的和小技巧分享。
好了,废话不多说,开始我们的升级之旅!
升级场景
ThinkSNS+ 一直依赖,都是保留 Laravel 的 commit 记录的前提下,进行开发,为了追随 Laravel 的升级,我们在本地的仓库中新建了一个分支,如果 laravel 更新频繁,则每周一进行 merge 操作。然后再发送到 ThinkSNS+ 的 GitHub 仓库上(仓库地址 https://github.com/slimkit/thinksns-plus )。所以此次升级同样采用 merge 的方式升级。
前端构建
Laravel 一直都有提供脚手架,5.5 则提供了 Vue 和 React 两种切换,对于前端老说,其实脚手架很优秀,但是不是适合所有场景,就和之前文字分享如何构建兼容 Laravel mix
辅助函数的前端构建一样,本次升级直接抛弃了脚手架。
包自动发现
说到「包自动发现」这个功能,其实 ThinkSNS+ 开发出来的时间比 Laravel 5.5 开发出来的时间还要早,最开始的时候,我们是采用 Composer 插件的方式来管理包清单,然后 ThinkSNS+ 使用这份清单进行服务提供者的加载。而后因为拓展包中有可能还会使用 Laravel 的拓展包,所以抛弃了 composer 插件的方式,我们从核心入手,选择在 composer.json
,然后这种方式一直在内部开发使用持续了大概三个月之久,后来关注 Laravel 5.5 开发动态,发现 laravel 5.5 选择从 vendor/composer/installed.lock
入手去匹配清单,比我们之前开发的更好,所以直接仿照 写了一份从 vendor/composer/installed.lock
匹配清单的代码。总结,这次升级对于半年前就开始使用这个功能的我们来说,影响太小了,以至于这次升级中,我们舍弃了之前维护的包包清单管理代码。而 之前的所有拓展包均可以正常使用。
JSON 异常消息
这块升级后确实影响蛮大的,因为之前所有 API 接口都是按照 5.4 的一个结构进行返回,升级后,5.5 的结构出现。被移动端头子给怼惨了,这块不说了,下午还要写文档,移动端需要兼容两个格式。
其他影响
因为 ThinkSNS+ 在开发的时候我们就遵循一个原则,所有 Laravel 的东西不动,需要的东西进行拓展,所以此次升级出了上述说的 json 消息以外,几乎没有任何影响。
了解更多 ThinkSNS+
上面的图是 ThinkSNS+ 安装后的默认首页。
上图是网站的后台部分页面截图,网站后台采用的是 ES6 + Vue 的 SPA,后台管理接口没有采用 token 认证,而是采用传统的 Session。这样有助于安全。
当然,我们也在为 ThinkSNS+ 开发一个友好的文档网站(之前一直在 github 中写 markdown )不涉及后端,文档使用 markdown 维护,前端使用 ES6 + React + Material-UI 进行开发。看图:
当然,正在开发中哈,暂未公布。
如果喜欢的童鞋可以点击 https://github.com/slimkit/thinksns-plus 帮我们点一个 Star 。感谢!!!
本作品采用《CC 协议》,转载必须注明作者和本文链接
网站后台采用的是 ES6 + Vue 的 SPA,后台管理接口没有采用 token 认证,而是采用传统的 Session。这样有助于安全。
@medz 请教下:为什么session更安全呢?
@lemayi 其实很好理解,如果采用 token 认证,网站没有采用 https 的话,很容易中间人攻击拦截获得权力,其次,xss 攻击也能直接读取存储在本地的token,都不是在浏览器环境安全的方式,而 session 存在客户端的key laravel 是经过加密的,而且即使 key 泄漏了,也很难认证成功,除非后端认证方式很老旧了。token 涉及到很多权限的,目前个人是还没有找到很好的方案,而 session 是相对安全的。
@medz 非常感谢回复!
但是我觉得有点勉强。我把token加密一下呢。那也和session一样了啊。
@lemayi 不,token一旦外泄,则可以在任何地方请求,无法准确验证真实性。
@medz token session区别不大,都有时效的。没有ssl的话,大家都是裸着的,token和session都会丢。
@Boomdawn 不不不,因为 token 我们采用的是 jwt ,意味着只要知道jwt的生命周期,就可以一直用下去。而 session 则不一样,比如半小时没有操作就退出,或者修改密码就过期了之前所有的加密认证。都是可控的。不然还要在程序中使用第二套token是得不偿失的。所以相对来说 session 比 token 好,针对后台管理这块。
@medz 你理解错jwt了吧,客户端还能手动续时间的?不知道你的key怎么生成签名。。。
@Boomdawn 我没说手动续期,而是你理解错了,jwt 的 token 过期时间有两个,且一个用户可以无限制的发放 jwt,我们来说这两个过期时间,一个是 auth 认证有效期,一个是刷新有效期,往往刷新有效期比 auth 认证有效期长,而 jwt 认证有效期到期后可以换取新的 token 继续使用,这个换取过程只是单纯的把之前的 token 列入黑名单,而不会印象发放的其他 token 这个是由于 jwt 的认证模型,采用的是 payload 拆解 token 自认证。我觉得是你理解错了。具体的 jwt 如何认证为有效,你可以看 https://jwt.io/ 的文档。
@Boomdawn 要让所有 jwt 过期的唯一方法有两个,例如使用 tymon/jwt-auth 包,则可以自己实现一个 storage 来进行控制。第二个,就是修改 secret 来让所有用户的所有 token 无效。
@Boomdawn jwt 你似乎忘记了一个东西,jwt server 有两个接口,一个是发放 token,另一个是刷新 token。
@medz Class App\User does not exist。。。
@lemayi 就上面的回复,因为我们采用的是 jwt ,所以 token 来验证后台管理的账户是否合法是不够安全的,尤其是中间人攻击或者xss的时候,而 session 虽然也无法避免,但是可以直接快速的对之前的认证进行过期。而且还要自动过期控制。当页面无操作一段时间,则自动退出登录。jwt 一旦token 被人拦截到了,只能更换 secret 来让整个应用所有用户 token 过期。其次,jwt 还可以续期,因为 jwt server 采用的是 auth.base 认证的,意味着一旦 token 被认为合法,就可以无限制的操作,并不会验证账户,如果要验证,还要单独写一套,得不偿失,后台本身属于低频操作,我觉得采用 session 对后台管理接口认证是较优方案,首先维护成本低,其次,可控能力优秀。我们用 token 虽然也可以达到,意味着,如果我们想非管理接口继续用 jwt ,需要对后台再实现一套 token 机制,例如 oauth2 授权,或者我们需要直接放弃 jwt 更换其他机制,都有点得不偿失。
@Qi https://github.com/slimkit/thinksns-plus/i...
https://github.com/slimkit/thinksns-plus/i...
这两个 issue 可以帮到你,你应该是运行了
php artisan vendor:publish --force
有--force
参数,强制覆盖了config.jwt.php
文件造成的,可直接git ckeckout config/jwt.php
解决。@medz 完美解决 3Q
@medz 刷新token的机制是自己实现,或者你使用的包所实现的。。。。
我自己实现的是,用同一个时间来判断是否能刷新,而不是两个时间。
不管是几个时间,你的理论都是错的,就像你的session是20分钟过期,我每5分钟请求一次你的带session接口,也会给我刷新啊。安全有啥差别我真看不出来,用session的好处是能在服务端维护一个用户的状态或者说是数据。用jwt的好处是无状态,天然分布式。
@Boomdawn 你这样即使不对的,你这样只在乎了后台的情况,根本不在乎前台用户的情况,其次,ts+ 的接口设计还要给 app 用,jwt 之所以给出两个过期时间,其中 jwt 建议 刷新时间高于 auth 认证有效期也是有原因的,因为一个用户可能我设置的有效期是两周,而刷新期是 3周,用户两周没用 则刷新后可继续使用。app 这样的场景很多,包括 QQ 也是这种策略。你的想法我觉得太多单一,为了满足一个需求而不顾全局。按照你这样说,确实解决了后台,也和 session 没啥差别。但是你的还增加了复杂度。同一个功能不采用简单的实现而选择复杂的,我觉得不是较优方案,做产品应该选择最合适的方式,而不是一味的推崇激进。而且,你只为了满足后台这个认证这一小块,如果后台设计多 server 来源呢?后端 spa 岂不是还要针对每个 serve 开发?session 则浏览器自动管理了标识。其次,你的做法还会为 app 和其他端的调用接口埋坑,当然,按照你的说法,我们可以再写一个解决,但是意义何在?还会增加复杂度,我觉得这不是一个产品该有的做法。这种做法自己玩怎么都可以。
@Boomdawn 我并无意与你真论谁对谁错,jwt 我是严格按照 jwt.io 来的,我们话题到此终止吧。因为你既然无视 jwt 的规范文档,我们继续讨论下去是没有意义的,其次,你一味的只解决当前场景而不考虑全局,也让我觉得无法接受你的建议。
@medz app每次启动,或者有固定钩子触发刷新就行了。如果客户两周或者三周都没有打开app或者触发到钩子。就让重新登录啊。 没觉得你说只照顾了后台是什么意思。。。。
井蛙不可以语于海者,拘于虚也;夏虫不可以语于冰者,笃于时也;
@Boomdawn 你的没错,我觉得你说的是对的,但是我觉得我不会修改,因为会增加复杂度。而 session 可以简单的解决的,当然采用简单的方式。感谢你的建议,之后开发新产品的时候或许我会考虑到你的建议,全局都采用 oauth2.0 的方式等等。
@medz 嗯嗯 谢谢接受我的说法。刚刚去翻了jwt协议并没有 refresh和fresh关键字。 这所谓的第二个时间,就是要自己实现,或者你用的包实现的,而不是jwt协议中的内容。不信你看 https://www.rfc-editor.org/rfc/rfc7519.txt
@medz @Boomdawn 感谢大家的积极讨论!越辩越明。喜欢这样的氛围!
@lemayi ?讨论很正常的。
加了你们的群,但没通过
@余威 你再加一下。
就知道是你们公司搞得。
JSON 异常消息这段明显是没有认真看 upgrade guide
@leo 不,看了的,但是我们决定不处理,而 client 的处理方式是 5.5 message 格式优先,然后不是这个格式再处理 5.4 格式。在之后的接口修改中,逐步修改为 5.5 的统一格式。这个影响并不大。
楼主屌炸天,回复都这么仔细