目录

最好的方法是限定几个可以访问 api 的域名,其他域名全部拒绝。
但是Access-Control-Allow-Origin只能设置一个值,所以要多端共用,只有header("Access-Control-Allow-Origin:*");

Ajax跨域请求带上COOKIE

前端:'xhrFields': {'withCredentials': true}(jquery ajax 设置),注意:Access-Control-Allow-Origin:* 与这个有冲突
A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true
后端:header("Access-Control-Allow-Credentials: true");跨域请求允许带cookie

web 客户端储存数据

前提:读写的数据必须要同域
使用 cookie 存储和读取
Web Storage (IE 789 无法使用)
IndexedDB 优点:支持事务,支持索引,可以存入对象,效率也不错。上手难
FileAPI 这个 API 可以结合 File 表单和 Formdata 从而实现异步上传文件。

如何保证只有自己的客户端才可以调用接口

api ajax 调用思考

如何保证多个客户端调用 api 接口时都是合法的(不是我们自己的客户端不能调用 api 接口拿数据),人为的(不是机器),数据安全的(不会被别人窃取数据),
首先要明白几点:
get 数据不可信,post 数据不可信,referer 数据不可信,host 域名 DNS 不可信,明文传输容易被抓包截取,cookie 可能被盗用!
Ajax 网站如何识别伪造请求?
好像参数不管怎么传,firebug 都可以看得到。
不过你可以在客户端将参数加密发送过去,如果在服务器端解密。
加密的密钥和解密的密钥才是最安全的
来路地址应该就是 referer,但这个东西一样是可以伪造的

好点的做法就是在验证用户时采用图片验证码的形式,给伪造带来很大的障碍(登录不了,就不能发帖),当然,你的图片验证码被分析出来了,那也是可能被攻破的.

另外 7L 的做法虽然可行,但是客户端加密的算法客户端也是能看到的,如果采用相同的加密方法一样可以伪造请求

首先只要是客户端发过来的,就不能叫伪造,
这个层面上要追究的其实是客户端的信用而非客户端的真伪.
你所谓的伪造应该指的是,用户在用你不希望的客户端(例如 机器人代替浏览器)

只能自己使用策略,不能相信客户端. 因为 referer 什么的都不可信.

如果是网站,限制客户端类型的原因通常为防止机器人或者为了展示广告.
常见策略:

  1. 服务端生成唯一 key 防止地址多次使用(甚至加上时间,过期无效)

  2. 有效图形验证码防止机器人

  3. 服务端生成唯一 key 禁止多端登陆(同一用户不同客户端同会话时间段多次登陆,key 不同则后登陆 key 有效,先登陆 key 强制注销).

  4. 服务端脚本+图形验证码 联合认证.例如如果一个下载页面同时 js 展示广告.
    为了展示广告同时要防止盗链,那么在 js 展示广告逻辑同时还用 js 调处图形验证码.

  5. 看一些当前流行的文件分享类站点,看他们的策略.例如 xxx 网盘.

http 是不安全,无状态协议。意味着你无法判断客服端是否是之前和你交流的某某。一般来说用 cookie 来识别客户端,但是 cookie 也可能被盗用。所以最应该做的是服务器段的逻辑,比如正常人可能一秒发一个帖子吗?不行就设定个帖子发送的间隔时间,只要应用层面可接受,那么不管其是人还是机器发过来的请求,都无所谓。
最常用的方法就是图形验证码。
至于判断数据来源,这个可以说完全没用了。现在很容易做到在合法来源处发送“不合法”数据。

自己目前的想法是,在服务器具端维护一个 api 调用 token 池,每次页面渲染,在服务器获取一个 api_access_token 储存在浏览器 cookie 中,每次 ajax 调用要将 api_access_token 作为参数发过来,服务器端验证过后,再处理 ajax 请求返回数据,
这个 api_access_token 生成规则,服务器端如何生成啊?何时失效啊?等等
总之,就是如何辨别是真用户,还是有人在模拟真实用户访问 api!!!

好的 api 应该满足

对于用户

  • 易学习:有完善的文档及提供尽可能多的示例和可 copy-paste 的代码,像其他设计工作一样,你应该应用最小惊讶原则。

  • 易使用:没有复杂的程序、复杂的细节,易于学习;灵活的 API 允许按字段排序、可自定义分页、 排序和筛选等。一个完整的 API 意味着被期望的功能都包含在内。

  • 难误用:对详细的错误提示,有些经验的用户可以直接使用 API 而不需要阅读文档。

对于开发人员

  • 易阅读:代码的编写只需要一次一次,但是当调试或者修改的时候都需要对代码进行阅读。

  • 易开发:个最小化的接口是使用尽可能少的类以及尽可能少的类成员。这样使得理解、记忆、调试以及改变 API 更容易。

开发一个好的 api 的总结

  • 面向用例设计
    如果一个 API 被广泛使用了,那么就不可能了解所有使用该 API 的用户。如果设计者希望能够设计出被广泛使用的 API,那么必须站在用户的角度来理解如何设计 API 库,以及如何才能设计出这样的 API 库。

  • 设计思路
    1面向用例的设计,收集用户建议,把自己模拟成用户,保证 API 设计的易用和合理

2保证后续的需求可以通过扩展的形式完成
3第一版做尽量少的内容,由于新需求可以通过扩展的形式完成,因此尽量少做事情是抑制 API 设计错误的一个有效方案

  • 避免极端的意见 1.必须漂亮(API 不一定需要漂亮)
    2.API 必须被正确地使用(用户很难理解如何正确的使用 API,API 的设计者要充分考虑 API 被误用的情况:如果一个 API 可能会被误用,那么它一定会被误用) 3.必须简单(我们总会面临复杂的需求,能两者兼顾的 API 是更好的 API) 4.必须高性能(性能可以通过其他手段优化,不应该影响 API 的设计) 5.必须绝对兼容(尽管本文一直提到如何保证兼容,但是我们仍然要意识到,一些极少情况下会遇到的不兼容是可以容忍的)

  • 有效的 API 评审 1.用例驱动,评审前必须提供完善的使用用例,确保用例的合理性和完备性。 2.一致性,是否与系统中其他模块的接口风格一致,是否与对称接口的设计一致。 3.简单明了,API 应该简单好理解,容易学习和使用的 API 才不容易被误用,给我们带来更多的麻烦。
    4.API 尽可能少,如果一个 API 可以暴露也可以不暴露,那么就不要暴露他,等到用户真正有需求的时候再将它成为一个公开接口也不迟。 5.支持持续改进,API 是否能够方便地通过扩展的方式增加功能和优化。

  • 提高 API 的可测试性
    API 需要是可测试的,测试不应依赖实现,测试充分的 API,尤其是经过了严格的“兼容性整合测试”的 API,更能保证在升级的过程中不出现兼容性问题。兼容性整合测试,是指一组测试用例集合,这组测试用例会站在使用者的立场上使用 API。在 API 升级以后,再检测这组测试用例是否能完全符合预期的通过测试,尽可能的发现兼容性问题。

  • 保证 api 的向后兼容
    对于每一个 API 的设计者来说,都渴望做到“向后兼容”,因为不管是现在的 API 用户,还是潜在的 API 用户,都只信任那些可兼容的 API。但向后兼容有多个层次上的意义,而且不同层次的向后兼容,也意味着不同的重要性和复杂度。

  • 保持逐步改善
    过去我们总希望能将现有的“不合理”的设计完全推翻,然后按照现在“美好”的思路,重新设计这个 API,但是在一段时间以后,又会碰到一样的状况,需要再推翻一次。如果我们没有有效的逐步改善的办法,依靠推翻现有设计,重新设计 API 只能让我们回到起点,然后重现之前的过程。 要有一套行之有效的持续改善的办法来在 API 兼容的同时,改善 API 使之更好。

  • 把握 api 的生命周期 1.告诉用户我们是如何设计的,避免误用,提供指导,错误的使用往往是缩短 API 寿命的一大杀手 2.提供试用期,API 不可能一开始就是稳定,经过试用的 API 才能有更强的生命力 3.为 API 分级:内部使用;二次开发使用;开发或试用中;稳定;弃用 API。避免 API 被滥用的同时,我们可以通过调整 API 的级别,来扩大其影响力,也能更优雅的结束一个 API 的生命周期。 4.开发 API 的过程其实就是一个沟通交流的过程。沟通的双方就是 API 用户和 API 设计者。

  • 一些具体的实施方案
    在一个 API 不可避免要消亡或者改变的时候,我们应该接受并且面对这个事实,下面列举了几种保证兼容性的前提下,对 API 进行调整的办法: 1.将 API 标记为弃用,重新建立一个新的 API。如果一个 API 不可避免要被消亡,这是唯一的办法。 2.为其添加额外的参数或者参数选项来实现功能添加 3.将现有 API 拆成两部分,提供一个精简的核心 API,过去的 API 通过封装核心 API 上实现。这通常用于解决用户需要一个代码精简的版本时。 4.在现有的 API 基础上进行封装,提供一个功能更丰富的包或者类。