这篇文章其实有点标题,因为微信网页授权本身不存在任何安全问题。确实存在安全问题的是一些不恰当的打开手势。讨论主要集中在授权过程中的错误报告和参数使用。如果您在开发过程中遇到过类似的问题,也许这篇文章可以帮助您。
了解微信网页授权
微信网页授权(官方文档)是公众号开发者在微信内嵌浏览器中获取用户基本信息的唯一途径。最重要的是获取用户的身份,这样才能实现支付等功能。因此,微信的意义不再只是授权登录。
一个简单的微信授权流程大致如下:
当然,在实际使用中,我们不会每次都要求用户授权。授权后我们会将信息写入到/中,所以一个相对标准的流程应该是:
如何使用
微信授权的参数中,有一个不起眼的可选字段。官方的描述是“重定向后会带上参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节”。乍一看,似乎只是一个标识字段,用于在授权前传递用户的状态。
但实际上,我们可以在回调地址中传递任意参数,也可以用来维护用户的状态,达到同样的效果。为什么我们需要设置单独的参数?
刚接触微信授权时,我根据业务需求做了微信授权转账服务。我将用它来确定用户在授权后应该访问哪个应用程序。比如用户需要去我们的商城,那么pass = mall.这种设计看似高效合理,却在不知不觉中引入了潜在的安全问题:
如果第二步授权中的微信301重定向URL被别人拦截了,我没有办法验证这个URL的请求者是否是我的真实用户,因为没有我可以用来验证的字段。只要动作够快或者贼够狠,这个恶意家伙就可以利用这个网址绕过微信的授权,以用户身份登录我们商城。而且由于设计过于简单,他甚至可以修改为任何连接的系统。
如果你使用过一些主流的微信支持组件,比如Ruby的gem包、PHP,你会发现他们的授权方式不支持定制,在授权时会进行对比和测试。对此,Ruby维护者Eric-Guo给出的解释是:
确实可以这样使用(定制化使用),但是设计目的其实是为了安全,也就是说这样设计的目的是为了防止有人冒充登录。 。
这也是为什么gem是内置来帮你填充的,而不是释放出来让你定制的。
总结一下,比较有效的用法是:
在授权开始之前生成并写入用户的 URL(也需要加密)。授权完成后,将URL与URL中的URL进行比较。如果不一致,则可以判定为非法请求。
如何处理错误
相信大多数开发微信授权的人都遇到过这个错误。对于这个错误报告,官方的描述是“非法”。排除真正代码错误的情况(这种情况几乎可以忽略),报错的原因通常是同一个代码被使用了两次。
事实上,这是微信的一项安全策略。用户授权码设计为一次性的,极大的防止了恶意者拦截记录回调网址,然后恶意访问绕过微信授权,实现欺诈登录。 。上一节提到同样的问题时,我用了“只要动作够快,不然就是小偷”的限制,因为只有他在用户跳转之前请求,才能成功冒充用户登录除了速度快之外,他还可以成功地以用户身份登录。你可以对返回的数据包进行篡改,让用户根本无法获取真实的URL,而他可以悠闲地进行操作。
为了解决这个错误问题,我花了很多时间检查日志,发现以下情况可能会触发:
用户授权跳转后,点击返回即可触发第二次请求。这种情况,要么是你没有记录用户的状态(),要么是用户的状态恰好丢失了(丢失或者失踪,都是小概率事件)。用户授权时,网速稍慢,等待时间有点过长。 ,因此页面在第一个请求返回之前刷新,触发第二个请求几乎同时收到两个相同的授权回调请求。不排除这是部分手机某些版本微信内置浏览的一些行为。另一个原因是用户授权完成,几秒后又发送了另一个IP。再次请求相同的 URL,