• 1. account + password [AES加密] timestamp直接放在url后API Server1.验证时间戳是否太长过期 2.验证url是否合法来源 3.验证用户信息这里需要注意的时,在进行发送登录信息时,需要确保两个安全: 确保发送的用户名、密码的安全 URL的来源合法及是否被人截取盗用JSONPOST解决问题一: 想要确保其安全,首先不能明文传输,将数据加密后传输,这样就算被人捕获到,想要得到真实内容也会增加他的成本,这里使用AES进行加密后传输 POST:data=aes(account+password组合的json数据) PS:此处登陆时aes的加密秘钥通过商议决定,之后aes的秘钥使用token作为key解决问题二: 要确保url来源的合法及是否被人盗用,可以采用对URL及参数进行签名。比如此处登陆url为:api.com/user/login 为了防止有人恶意请求及冒名请求,手段如下: $val = sign(api.com/user/login?timestamp=12345+apiVersion) apiVersion会在初始化接口返回,时间戳也会在初始化时与服务器进行对时。 REQ:api.com/user/login?timestamp=12345&sign=$val 服务器收到后,首先检查时间戳是否间隔太久。然后会去掉sign,对剩余部分进行相同算法签名,然后比较二者是否一致与服务端通信
  • 2. 伪代码POST数据(已登录为例) POST URL: http://api.com/user/login?timestamp=123456& nonce=1234&signature=xxxxx get(账号+密码); aesData = aes(data, secret); // data是获取到的表单key1=value1&key2=value2形式数据,获取token后加密将使用token postToServer(aesData); PS:如果涉及到图片上传的form,此字段无需加密URL签名 data = initApi();// 启动时初始化,获取初始信息,如:secret、serverTime等 // 字典排序 tmpArr = [secret, timestamp, nonce]; sort(tmpArr, SORT_STRING); tmpStr = implode(tmpArr);// 链接成字符串 tmpStr = sha1(tmpStr);// sha1加密 拼接URL: http://api.com/user/login?timestamp=123456& nonce=1234&signature=tmpStr PS:所有请求GET|POST|DELETE|PUT|PATCH均要进行url签名操作注意点: 初始化获取的secret,仅用于第一次用户登录AES加密的key。服务端返回token,也用该值作为key进行解密。 获取到token后,aes加解密,均使用该32位长度的token(url 签名一直使用初始获取的secret)。 此设计目的:为降低被截取的风险, token只在获取时进行一次网络传输。之后作为AES KEY使用保存本地。服务端根据userID来获取token进行解密或加密
  • 3. APP数据更新四种方式(1)通过服务端数据接口,全量刷新数据。 数据更新频繁的条件下可以使用这种方式。 数据量特别小的时候也可以使用这种方式,每次重新取全部数据代价不大。 比如:动星2.0,TATA1.0(2)通过服务端数据接口,增量更新数据。 增量更新数据可以大幅度降低网络流量,降低服务器压力。 增量更新需要服务端与客户端做一些约定。 比如可以按时间更新,服务端每次数据发生变化(增删改)都需要记录更新时间。数据不允许物理删除、只可以逻辑删除。客户端根据更新时间取得该时间之后发生变化的数据并存储到本地。 另外可以通过版本号的方式对数据进行更新,客户端先从服务器端取得版本号,如果版本号变更了,则重新取数据,这应该算是一种半增量更新的方式。(3)使用WebView嵌入Web页面,实时更新数据。 这种情况实际上等同于网站的效果。 缺点是WebView目前性能上还差一个档次,需要较长的响应时间。另外每次访问需要下载整个页面内容,流量较大。 优点是跟网站一样,可以快速修改部署,可以在服务端定制包括UI在内的整个页面内容。(4)使用WebView嵌入Web页面,Web页面存储在本地,实时更新Web页面。 支付宝采用此结构。 对比3来说,4的优点是不用每次都重新下载html、css、javascript,仅需在页面发生更新的时候,重新将整个页面打包下载更新。 页面内的数据依然可以使用数据接口的方式获取。
  • 4. 数据增量更新概念 增量更新是指在进行更新操作时,只更新需要改变的地方,不需要更新或者已经更新过的地方则不会重复更新,增量更新与完全更新相对。这种更新的概念应用范围比较广泛,凡是需要进行数据更新的地方都会用到,如软件更新、数据库更新、杀毒软件的病毒库更新、CMS更新和路由表更新等。 特点 只更新需要更新的地方; 相对于完全更新更快捷,处理量减少; 采用增量更新需要在更新前设定规则,规定更新的策略; 应用案例 App store应用下载、Android应用下载 微博首页、微信朋友圈 什么时候更新数据: 1、某些特定场景触发更新。 例如打开应用、应用从后台进入前台、用户登录、用户进入某一页面。 2、子线程定时更新数据。 专门起一个线程用来更新数据。Android下经常采用此种方法。 通常数据的获取/更新是异步的,首次打开应用除外。
  • 5. 增量更新两种方案对比 对比就是客户端请求服务端所有关键数据,跟本地已有的数据进行对比,筛选出增删改的数据进行更新。 它的好处是服务端什么都不用做,但是加大了客户端的的逻辑复杂度,耗费更多的流量[与全量刷新一致] 这种方案对于[增删]根据id非常容易判断出来,但是如果对比[修改]则比较麻烦。 采用的优化方案是,对于数据增加一个tag,根据对比server与app本地数据tag,不一致则表示数据已经更新,根据对应的id更新对应数据即可。 当然如果不方便生成该tag,也可以根据对应数据的hash值来进行判断。 邮件协议IMAP,日历协议CalDAV就是用这种方式做增量更新日志 日志指服务端记录数据的每一次增删改,用一个类似版本号的sync-key标记这次修改,客户端通过一个旧的sync-key向服务端请求,服务端返回这个sync-key与最新sync-key之间所有的修改给客户端,完成增量更新。 这个sync-key在服务端的实现上可以是时间,也可以是一个自增的id,sync-key之间有顺序关系就行。整体关系可以描述如下图: 使用这种方式,要注意在一个sync-key区段内数据量非常大时,更新数据非常大。解决方式是分多次请求,每次请求app与server约定一个阀值(对应我们就是每次获取几条数据)。文章来源:http://blog.cnbang.net/tech/2258/
  • 6. 增量更新实现描述首先从DB中取出数据放入Cache中,这里假设首页数据为列表。此时设置index_sync_key=0 此时,APP端第一次拉取数据,直接从Server缓存中获取指定条目的数据。 新增 当DB中增加数据时(1条或多条),首先更新Cache,根据增量更新的原则,这里只是将新增加的数据插入到缓存的合适位置。同时更新index_sync_key=1,并对将新增的数据记录其中(除了数据本身还有数据位置信息) 此时如果APP端请求服务器,服务器根据index_sync_key=0,则返回index_sync_key=1的信息。APP端根据返回信息只修改新增到index_sync_key=1中的内容。 更新 当对DB中id=1的数据更新时,先更新Cache,然后另外更新index_sync_key=2,此时APP端请求数据时,传输过来index_sync_key=1,根据对比,将index_sync_key=2中的内容返回,APP端收到数据后,明确这是更新的内容,然后针对id=1的数据进行更新,其他内容不改变。 删除 当在DB中删除数据时,假设为id=2,那么此时更新Cache,将id=2的数据移除,然后更新index_sync_key=3,此时APP端拉取数据时传过来的是index_sync_key=2,发现有大于2的情况,于是返回id=2被删除的情况。APP本地将id=2的数据移除。 PS:以上涉及到了对数据的【增改删】的情况处理。增量更新也就是对变化的数据进行处理的机制。这里有两种比较麻烦的情况。分别说明
  • 7. sync_key存在多个差值当APP端请求的index_sync_key=1,Server端对应的是index_sync_key=1001的时候,这时候本来需要返回1000条数据,那么网络传输时间会非常长,耗费资源。此时如果采用阀值的方式,那么中途可能会涉及对同一个数据进行多次修改。而且每次拉取获取的还不是最新最确定的内容。 解决办法: 个人采用对于sync_key如果差距较大,直接拉取最后一个版本的sync_key的内容,而不是根据sync_key的中间差距进行分批次拉取。sync_key同一个中,存在[增删改]多种情况相比上一种情况,这种问题容易解决的多。对于sync_key中存在的多种情况,APP端进行批量的判断即可,该增加的增加,该移除的移除,该更新的更新。