如何区分HttpRequest来自微信小程序还是浏览器?
最近有些同学咨询我,当后端接收到一个request的时候,如何区分是来自于微信小程序还是浏览器的请求?
首先,微信小程序的请求并没有明确的标记位来验证请求来源。
一、网上的一些说法:
1、Header中的content-type
微信小程序的content-type默认“application/json”,POST请求一般自己定义为 “application/x-www-form-urlencoded”。如果是PC浏览器直接请求URL,content-type确实是null的,很多网友觉得可以使用这个区分。但是一旦我们在浏览器中通过Ajax请求,content-type就不是null了,就没办法区分是小程序的还是Ajax脚本的。
2、Header中的User-Agent
User-Agent可以区分终端类型。
如果是微信中请求,agent中有 MicroMessenger 字符串,其他则没有!在一定程度上可以解决来源,但是不能解决根本问题。因为,可以直接复制url,在微信聊天中打开!
3、sessionid
因为微信小程序(包括公众号)的request请求都是无状态的,也就是说session是无效的。(我们可以在后台打印一下sessionid,就会发现每次request的sessionid都是不一样的,所以session是无状态的。)
所以,有的同学就模拟一个session:后端保存sessionid到内存或缓存,然后每次请求都带上sessionid,比如用url?JSESSION=sessionid,或者在Header中添加Cookie的形式,以此来判断和校验用户是否登录或是否来自于小程序。
但是如果我们是Fiddle之类的工具抓取请求,就会获得请求的参数sessionid,同样的可以通过Ajax脚本来模拟(sessionid)请求服务器端。所以也是不安全的。
二、我的做法:
首先用User-Agent来做基本筛选!
然后:
1、在登录的时候,一定要用wx.login获取code,然后服务器端通过code获取sessionkey和openid来实现登录。sessionkey的有时效(timeout)的,类似于session有效时间。
2、获取sessionid,并将sessionkey、openid和sessionid的关系,存储到服务器内存或缓存中。这个关系开发者可以自己定义,一般我用map。
3、前端重新封装wx.request,将sessionid保存到globalData中,globalData有失效时间,这样sessionid的有效时间和sessionkey就一致了。所以,每次请求要带上sessionid,后台校验sessionid 和 sessionkey的关系。
4、只有sessionid并不能解决csrf攻击(前面有说明)。还需要使用一个csrf-token,就是每次请求都会产生一个csrf-token返回给前端,前端下次请求的时候带上csrf-token,后端校验。 这里有一个问题,如果抓到response中的内容,就可以拿response中的csrf-token进行模拟访问了,所以我们需要对csrf-token处理一下
5、csrf-token处理:可以用加密的方式,只要保证后端同样的加密或解密能够将token匹配即可。也可以简单的通过移位、或者添加字符串等方式。总之这个方式只有开发者知道,前后端怎么处理token来校验有效性!
6、为了保证绝对的安全,在一些关键业务的处理上,最好用wx.login产生code,后端根据code调用微信服务器接口进行校验后再处理!
三、更好的方式?
这只是我个人的思路,如果你有更好的处理思路,可以留言,一起交流!
谢谢!
共同学习,写下你的评论
评论加载中...
作者其他优质文章