zoukankan      html  css  js  c++  java
  • 接口安全性解析

    针对
    --->非开放性平台
    --->公司内部产品
     
    接口特点汇总:
    1、因为是非开放性的,所以所有的接口都是封闭的,只对公司内部的产品有效;
    2、因为是非开放性的,所以OAuth那套协议是行不通的,因为没有中间用户的授权过程;
    3、有点接口需要用户登录才能访问;
    4、有点接口不需要用户登录就可访问;
     
    针对以上特点,移动端与服务端的通信就需要2把钥匙,即2个token。
    第一个token是针对接口的(api_token);
    第二个token是针对用户的(user_token);
     
    先说第一个token(api_token)
     
    它的职责是保持接口访问的隐蔽性和有效性,保证接口只能给自家人用,怎么做到?参考思路如下:
    按服务器端和客户端都拥有的共同属性生成一个随机串,客户端生成这个串,服务器也按同样算法生成一个串,用来校验客户端的串。
    现在的接口基本是mvc模式,URL基本是restful风格,URL大体格式如下:
    http://blog.snsgou.com/模块名/控制器名/方法名?参数名1=参数值1&参数名2=参数值2&参数名3=参数值3
     
    接口token生成规则参考如下:
    api_token = md5 ('模块名' + '控制器名' + '方法名' + '2013-12-18' + '加密密钥') = 770fed4ca2aabd20ae9a5dd774711de2
    其中的 
    1、 '2013-12-18' 为当天时间,
    2、'加密密钥' 为私有的加密密钥,手机端需要在服务端注册一个“接口使用者”账号后,系统会分配一个账号及密码,数据表设计参考如下:
    字段名 字段类型 注释
    client_id varchar(20) 客户端ID
    client_secret varchar(20) 客户端(加密)密钥
    (注:只列出了核心字段,其它的再扩展吧!!!)

    再说第二个token(user_token)
     
    它的职责是保护用户的用户名及密码多次提交,以防密码泄露。
    如果接口需要用户登录,其访问流程如下:
    1、用户提交“用户名”和“密码”,实现登录(条件允许,这一步最好走https);
    2、登录成功后,服务端返回一个 user_token,生成规则参考如下:
    user_token = md5('用户的uid' + 'Unix时间戳') = etye0fgkgk4ca2aabd20ae9a5dd77471fgf
    服务端用数据表维护user_token的状态,表设计如下:
    字段名 字段类型 注释
    user_id int 用户ID
    user_token varchar(36) 用户token
    expire_time int 过期时间(Unix时间戳)
    (注:只列出了核心字段,其它的再扩展吧!!!)
    服务端生成 user_token 后,返回给客户端(自己存储),客户端每次接口请求时,如果接口需要用户登录才能访问,则需要把 user_id 与 user_token 传回给服务端,服务端接受到这2个参数后,需要做以下几步:
    1、检测 api_token的有效性;
    2、删除过期的 user_token 表记录;
    3、根据 user_id,user_token 获取表记录,如果表记录不存在,直接返回错误,如果记录存在,则进行下一步;
    4、更新 user_token 的过期时间(延期,保证其有效期内连续操作不掉线);
    5、返回接口数据;
     
    接口用例如下:
     
    1、发布日志
    URL:  http://blog.snsgou.com/blog/Index/addBlog?client_id=wt3734wy636dhd3636sr5858t6&api_token=880fed4ca2aabd20ae9a5dd774711de2&user_token=etye0fgkgk4ca2aabd20ae9a5dd77471fgf&user_id=12
    请求方式:  POST
    POST参数:title=我是标题&content=我是内容
    返回数据:
    {
          'code' => 1, // 1:成功 0:失败
          'msg' => '操作成功' // 登录失败、无权访问
          'data' => []
    }

    对于 api_token 的校验,其安全性还可再增强:

    增强地方一:

    再增加2张表,一个接口表,一个授权表,设计参考如下:

    接口表

    字段名 字段类型 注释
    api_id int 接口ID
    api_name varchar(120) 接口名,以"/"作为分割线,如 blog/Index/addBlog
    api_domain varchar(256) 所属领域
    is_enabled tinyint(1) 是否可用  1:可用 0:不可用
    add_time int 添加时间(戳)

    (注:只列出了核心字段,其它的再扩展吧!!!)

    授权表

    字段名 字段类型 注释
    client_id int 客户端ID
    api_id int api编号
    api_name varchar(120) 接口名,以"/"作为分割线,如 blog/Index/addBlog
    is_enabled tinyint(1) 是否可用  1:可用 0:不可用
    add_time int 添加时间(戳)
    expire_time int 过期时间(戳)

    (注:只列出了核心字段,其它的再扩展吧!!!)

    执行过程如下:

    1、移动端与服务端生成的 api_token 进行对比,如果不相等,则直接返回错误,否则,进入下一步;

    2、根据接口URL,组装 api_name,再加上客户端传回的 client_id 为参数,查找 “授权表”记录,如果记录存在,且有效(是否可用,是否过期),则表示权限验证通过,返回接口数据,否则返回错误信息;

    增强地方二:

    对于一些很特殊的接口,怎么特殊,哪些算特殊,我也不知道,总而言之,就是感觉http请求有可能被劫取,传递参数有可能被窜改等情况,还是举个例子来说吧:

    有个直接转账接口,页面上 我输入的是5元,表示我要给对方某某转账5元,结果在http传递过程中,被人劫取并窜改成了 10000元,而且入账对象改成了“黑客”的账号,那不是亏大发了,思考了一下,应该有2种方案解决这个问题,

    方案一:走https,这个就不多说,比较公认的安全机制;

    方案二:走数字签名,实现原理如下:

    一个http请求,假如需要传递如下3个参数

    参数名1=参数值1

    参数名2=参数值2

    参数名3=参数值3

    我们可以再追加一个参数,该参数的名为 identity_key (名字是什么不重要),该参数的值为 加密密钥')

  • 相关阅读:
    2018 ACM 网络选拔赛 徐州赛区
    2018 ACM 网络选拔赛 焦作赛区
    2018 ACM 网络选拔赛 沈阳赛区
    poj 2289 网络流 and 二分查找
    poj 2446 二分图最大匹配
    poj 1469 二分图最大匹配
    poj 3249 拓扑排序 and 动态规划
    poj 3687 拓扑排序
    poj 2585 拓扑排序
    poj 1094 拓扑排序
  • 原文地址:https://www.cnblogs.com/yyjie/p/7487003.html
Copyright © 2011-2022 走看看