最近在研究运动软件Keep,就是那个自律给我自由
的Keep。主要方法是使用Charles来抓包,然后查看接口。由于Charles
是一款Mac的应用,所以Windows
系统,可能不能实践了。另外安卓手机限制不能抓包HTTPS的协议,所以也不能实践了。
现在分享一下我的研究成果,本文可能触及到Keep软件的一些特殊操作,大家谨慎使用,本文仅供学习和交流使用,如果侵犯到Keep的相关利益,请联系我。
Keep是典型的混合式开发,也就是前端H5 + 后端 + 移动端(安卓和iOS)
,大多界面都是使用了前端技术开发的,主要前端框架是基于VUE来做的。
主要域名
后端服务域名:https://api.gotokeep.com
主站H5:https://show.gotokeep.com
活动等H5:https://m.gotokeep.com
静态资源CDN:https://static1.keepcdn.com
监控:https://apm.gotokeep.com
智能设备:https://kit.gotokeep.com
userAgent
userAgent
是混合开发中,H5用来识别APP内部与外部的重要依据。前端可以通过JavaScript
代码window.navigator.userAgent
来获取,Keep
的userAgent`如下:
Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;Keep/6.43.0 (iPhone; iOS 13.5.1; Scale/2.00);Keep/6.43.0 (iPhone; iOS 13.5.1; Scale/2.00)
当然不同系统是不一样的,其中最重要的是最后Keep/版本号(其他信息)
这一段,至于为什么要写2遍,我也不清楚,难道客户端植入的时候多写了一遍?
调试页面
Keep线上的页面都是线上环境,调试线上环境的其实也没有多大的意义。由于我们拿不到Keep的源代码,所以只能通过线上代码简单地看看Keep页面的结构。
Keep使用了vue + vue-router + vuex
这样的框架组合,它的页面链接的最后一级是用户的userId,我们以“我的等级”页面为例,如:https://show.gotokeep.com/experience/grades/xxxxxxxxxxxxxxxxxxxxxxxx?kg=16
其中xxxxxxxxxxxxxxxxxxxxxxxx
就是userId,由于用户的userId是隐私数据,所以我就那x来代替了(下面所有有userId的地方,我都会用xxxxxxxxxxxxxxxxxxxxxxxx
来代替)。
浏览器直接打开这个页面,发现报错了,仔细一看,你会发现是接口https://api.gotokeep.com/diamond/v1/users/xxxxxxxxxxxxxxxxxxxxxxxx/privilegeWall/levels
返回了401
,接口401
说明没有授权。为了让页面实现在Keep中同样的效果,可以做下面的几步:
让H5页面识别浏览器为Keep站内。
要识别站内就是使用上面的
userAgent
,打开开发者工具,然后选择Network conditions
面板,去掉Select automatically
的勾选,然后把上面的userAgent
粘贴到下面的输入框中,如下,然后刷新一下userAgent
就生效了。获取cookie。
Keep接口认证是基于
JWT
来实现的。我们使用Charles
来查看任一接口的cookie
,会发现有一个authorization
的字段,这个就是JWT
的关键,如下:设置cookie。
为了页面能正常运行,我们把所有的
cookie
信息,都设置进去。打开浏览器的开发者工具,然后依次把cookie
粘贴进去,如下:
此时刷新页面,可以看到页面已经可以正常运行了,如下:
客户端事件
客户端事件是H5和客户端(这里只有移动端)交互的指令,其实就是一个特定协议的字符串,前端使用location.href = 客户端事件字符串
来执行客户端事件,在Keep中为了方便调试,也可以扫码来执行这些事件。举个例子,打开webview的事件是keep://webview/
后面跟着encode的URI就可以实现跳转页面了,比如要使用Keep来跳转本博客,就可以如下:keep://webview/https%3a%2f%2fwww.kai666666.com%2f
,你可以使用这个工具来encode,把刚才的事件,转换为二维码,如下:
现在打开Keep扫一扫,上面的二维码,你就可以用Keep进入本博客网站了。要把字符串转换为二维码可以使用草料二维码。
在https://api.gotokeep.com/config/v2/basic?refresh=true
接口中定义了更多的事件:
描述 | 事件 |
---|---|
精选 | keep://discover_web |
训练 | keep://discover_course |
饮食 | keep://discover_food |
商城 | keep://discover_store |
精选 | keep://discovery/explore |
训练 | keep://discovery/course |
攻略 | keep://discovery/guide |
饮食 | keep://discovery/diet |
商城 | keep://discovery/product |
推荐 | keep://hottabs/hot |
热门视频 | keep://hottabs/video |
运动时刻 | keep://hottabs/story |
training_训练课程 | keep://discover_course/ |
activity_热门活动 | keep://hot_activities |
hashtag_话题讨论 | keep://hashtags_index |
group_小组推荐 | keep://groups_index/ |
kol_达人推荐 | keep://recommend_keepers/ |
article_精选文章 | keep://selections |
热门 | keep://timeline/hot |
关注 | keep://timeline/follow |
逛逛 | keep://timeline/wander |
训练 | keep://homepage/content?tabId=ZnVsbENvbnRlbnQ= |
跑步 | keep://homepage/running?tabId=cnVubmluZw== |
瑜伽 | keep://homepage/yoga?tabId=eW9nYQ== |
行走 | keep://homepage/hiking?tabId=aGlraW5n |
骑行 | keep://homepage/cycling?tabId=Y3ljbGluZw== |
Kit | keep://homepage/keloton?tabId=a2Vsb3Rvbg== |
数据中心 | keep://datacenter?type=all&period=day |
跑步历史记录 | keep://datacenter?type=running&period=day |
每周目标 | keep://weeklypurpose |
身体档案 | keep://bodydata |
运动能力 | keep://physical_test_list |
运动概况 | keep://physical_summary |
运动日记 | https://show.gotokeep.com/usersfulldiary |
步数记录 | keep://steps_dashboard |
连接应用和设备 | keep://oauth/list |
我的收藏 | keep://my_favorites |
我的活动 | keep://activities |
训练营历史 | keep://bootcamp/history |
我的路线 | keep://my_running_routes |
我的运动小队 | https://show.gotokeep.com/outdoor/groups/list |
我的最佳成绩 | keep://running/best_records |
我的 Class | keep://classes/mine |
购物车 | keep://shopping_cart |
我的钱包 | https://show.gotokeep.com/wallet |
优惠券 | keep://store_coupons |
购买记录 | keep://purchase_history |
Keepland 课程 | https://keepland.gotokeep.com/my_course?pulldownrefresh=true |
从上面可以看到很多https://show.gotokeep.com
开头的地址用Keep扫码也是可以直接进入的,但是我们自己的https
网站却不能,可见Keep对自己的白名单内的域名做了特殊处理(相当于其他页面使用了keep://webview/
事件)。
小应用
Keep并没有提供一种查看自己跑了多少个全马,或者跑了多少个半马这样的功能。现在我们写个脚本把自己的跑步数据存入我们自己的数据库中,并通过SQL查询出我们跑了多少个半马。
这里假设你已经安装了MySQL
,并且已经建立了一个名叫keep_running
的数据库。
建表脚本如下:
1 | DROP TABLE IF EXISTS running_data; |
要得到自己的跑步数据,可以调用https://api.gotokeep.com/pd/v3/stats/detail
接口来获取,由于浏览器端会有跨域的问题,所以我们就直接跑一个node脚本就行了。
这里需要用到额外的两个库,一个是axios,用来发送http请求的;另一个库就是mysql,用来把数据存到数据库的。大家自己运行npm install一下。
脚本大致如下:
1 | const axios = require('axios').default |
注意上面headers
处,需要换成自己数据的键值对形式,在Charles
中获取方式如下:
最后你就可以通过SQL语句查询数据了:
1 | # 全马 |
通过数据查询可以看出我自己跑了10个半马了😀。