postman 实现API自动化测试

编 写:袁 亮
时 间:2017-01-16
说 明:postman 实现API自动化测试


一. 实现目的

  1. 接口开发调试工具
  2. 自动化测试
  3. 接口用例团队内共享
  4. 降低接口文档编写成本

二. 实现流程

  1. 团队使用同一份文档
    测试文档存入代码仓库
    使用前从代码仓库拉取导入
    修改完之后,重新导出,并更新代码仓库
    ps:后续为了降低代码层级,可以将API分成很多个collection,前期先合并成同一个

  2. 使用工具产生文档
    postman:界面gui模式
    newman:服务端cli模式

三. postman产生文档

  1. 通用层实现 在collection上做
    • 所有接口都先放在同一个collection,后期根据模块拆分
      方便在同一个collection上实现一些通用逻辑
    • 环境变量支持
      appid: 10101
      appsecret: 8e2160ec2b07f1faca9055be530bf09d
      host: http://api.shop.ci123.com/
      maxtime: 300
    • pre-request中实现签名
    • tests中实现统一的校验
      http状态码 200
      返回json,并且需要包含state和mess字段
      接口超时时间
      签名出错
  2. 目录层级规范
    • 根据模块不同,创建不同的文件夹
    • gui展示的原因,目录层级最多3层
    • 每一个接口,都是一个文件夹 (所以实质上除了collection只有2层目录)
    • 最底层的文件夹下,所有请求都是同一个接口的不同用例
  3. 具体实例实现
    • url地址
      {{host}}/Item/getSkuByItemId?appid={{appid}}
    • post参数增加两行
      expire {{expire}}
      mdstr {{mdstr}}
      ps:因为request只读的原因,不能追加,只能在每个地方都写一次这个
    • 填入其他请求参数,构造每一种apiReturn的情况
      一个用例只实现一个对应apiReturn,这个return可能有多种情况,放在examples里
    • 每个用例,必须增加tests,来告知是否通过
      除了最终成功的那个请求,其他请求的tests主要就是校验state状态码即可
    • 执行成功的用例校验
      写请求:一般是校验对应的id是否正确,比如订单id,商品id等
      读请求:解析对应的json数据格式,是否包含什么样的字段等等
      ps:后续谁有空可以看下,是否可以自己定义模板,现在看到的那些模板只能选择使用,不能自己创建
  4. 开发调试规范
    • 从代码仓库把文档导入到postman
    • 接口编写过程中,使用这个来进行调试,所有情况必须测到
      有多少个state返回,就最少有多少个接口用例
    • 接口全部写完之后,必须通过runner来确保所有用例全部跑通
      不要出现改到后面,前面的跑过的用例又跑不了
    • 写完之后,把postman里的数据导出到git仓库中

四、自动化测试 todo

  1. 安装newman环境
  2. 定时或者在git的钩子里设置
  3. 拉取对应的文档,执行测试
  4. 测试结果入库
  5. 展示报警
    工作台展示
    邮件、短信报警

五、postman常用操作

  1. 设置
    皮肤设置
    返回值解析设置:json auto的时候,没有自动识别是json
  2. 环境变量设置与使用
  3. 数据导入导出
    collection导入导出
    整体导入导出
  4. 复制修改
    用例复制,文件夹复制等
  5. examples使用
    可以配合做mock server
  6. runner使用
  7. console控制台调试
  8. 搜索
  9. API文档发布
    免费版有限制,可以大概看看
  10. 官方文档,可以快速看一遍
  11. 错误提示
    特别是全局变量中的
  12. runner里执行的时候,一定要注意request的是要保存里的,不然更改了是无效的
    send本身是直接起效
  13. ctrl + s保存修改
  14. Codeception

npm私有包:键盘事件监听


编   写:袁 亮
时   间:2017-08-17
说   明:复杂页面交互,键盘快捷键监听组件

一、功能描述
    1、事件监听
        默认绑定keydown事件
        绑定单例,防止多次绑定,导致多次触发
            ps:vue如果代码自动刷新,会导致又绑定一次
    2、触发条件
        配置条件
            inInput:光标在输入框内是否触发
                true:触发,false:不触发,默认true
            needCtrl:是否需要同时按下ctrl键
                不传,不限制
                true:必须按下Ctrl
                false:不能按下Ctrl
            needShift:是否需要同时按下shift键
                同needCtrl
            needAlt:是否需要同时按下alt键
                同needCtrl
        自定义方法
            触发的时候,会执行该方法判断是否要执行,返回true或者false
            不传,默认true
    3、事件触发执行
        同一事件,多次绑定
            后绑定的优先级更高
        事件冒泡
            如果事件没有被响应,自动按绑定顺序冒泡
        事件互斥
            同一事件,只会触发一次,捕获后,不再冒泡
        默认行为阻止
            事件被捕获,默认行为将被阻止
    4、事件定义
        内置常见事件
            esc:取消
            backspace
            enter
            delete
            up
            down
            increase
            decrease
            
            number:数字
            float:浮点数
            letter:字母
        支持自定义事件配置
            优先级高于内置事件
        
二、使用方法
    1、安装包
        npm install @duomai/keylisten --save
        ps:先切换到多麦的源
    2、代码
        import KeyListen from '@duomai/keyListen'
        
        // 在created钩子里,使用内置事件,不需要setConfig
        KeyListen.setConfig(config.shortcutKey).add({
          up: function () {
            // todo up
          },
          down: function () {
            // todo down
          }
        })
        
    

npm私有仓库3:项目中使用


编   写:袁 亮
时   间:2017-08-15
说   明:npm私有仓库3:项目中使用

一、修改dns地址 192.168.0.224
    1、linux
        vim /etc/resolv.conf
        nameserver 192.168.0.224
    2、windows
        网络设置
        清除缓存 cmd命令行
            ipconfig /flushdns
            
二、nrm管理npm源
    1、安装
        npm install -g nrm
    2、添加私有源
        nrm add duomai http://npm.duomai.com
    3、查看所有源
        nrm ls
    4、使用私有源
        nrm use duomai
        
三、安装包
    1、私有包(跟其他包一样,只是多了一个统一的前缀)
        npm install @duomai/urls
    2、普通包
        npm install vue
    3、包查看
        http://npm.duomai.com
    4、注意事项
        如果私有包使用es6的语法写,webpack打包的时候,需要将其使用babel转换,否则打包的时候会报错
        {
          test: /\.js$/,
          loader: 'babel-loader',
          include: [resolve('src'), resolve('test'), resolve('node_modules/\@duomai')]
        }
    
四、使用参考 @duomai/urls
    1、安装
        npm install @duomai/urls --save
    2、全局引入,设置
        import Urls from '@duomai/urls'
        
        Urls.init({
          store_id: Login.state.data ? Login.state.data.store_id : '' // 链接公共参数注入
        }, {
          shop: process.env.SHOP_BASE_URL, // 测试链接前缀注入,可以不写,默认正式环境
          seller: process.env.SELLER_BASE_URL,
          dealer: process.env.DEALER_BASE_URL
        })
    3、组件中使用
        import Urls from '@duomai/urls'
        console.log(Urls.shop.item(1921))

Vue开发快速起步


编   写:袁 亮
时   间:2017-06-28
说   明:Vue开发快速起步

一、工作模式
    1、类似jquery,作为类库
    2、单文件组件方式
        开发环境
            node hot reload
        生产环境
            静态html
            任意部署在webserver下即可
    
二、安装起步
    1、环境安装
        node npm vue vue-cli 等安装
    2、项目脚手架安装
        vue init webpack {project_name}
        cd {project_name}
        npm install
            ps:vim config/dev.env.js 修改开发环境端口,默认8080很有可能被占用
        npm run dev
            放在后台运行:nohup npm run dev & 
    3、访问
        http://192.168.0.249:8081
    4、IDE
        webstorm
        sublime
        vscode
    5、其他模块安装
        vuex的安装
            npm install vuex --save
        修改package.json
    6、编译
        npm run build
        
三、开发环境访问流程
    1、index.html
    2、src/main.js
        类似php框架的index.php
    3、src/App.vue
    4、router/index.js
        规则匹配,进行转发
        路由处理
    5、components/Hello.vue
        具体处理逻辑
        可以包含其他的组件
        
四、组件开发
    1、类库文件引入
        1.1 引入
            import
                必须在最开始的地方加,不能放在条件判断等
            require
                可以在条件判断里
        1.2 类库导致
            export default
            module.exports
    2、组件引入
        2.1 html结构
            
            
        2.2 组件源
            import modalMember from '@/components/modalMember.vue'
        2.3 注册?
            components: {
                modalMember
            }
    3、组件数据
        3.1 父组件数据传递 props
            props验证
            值传递 引用传递
            单向数据流
        3.2 组件本身数据 data
        3.3 组件计算属性 computed
            method的区别,缓存,依赖
            getter
            setter
        3.4 数据监听 watch
            vs computed
            异步、开销大的时候,用watch
    4、模板语法
        4.1 文本
            {{}}
            v-text
            v-html
            v-once
                不更新
        4.2 属性
            v-bind:{name}
            简写 :{name}
            :class 注意注意
        4.3 条件属性
            v-if
            v-else-if
            v-else
            v-show
        4.4 循环 v-for
        4.5 事件
            v-on:click
            @click
        4.6 输入数据双向绑定
            v-model
            修饰符
                .lazy
                .number
                .trim
        4.6 注意事项
            a. 以下对数组操作,不会触发视图变更
                当你利用索引直接设置一个项时
                当你修改数组的长度时
            b. 视图更新队列
                数据变更,视图更新会放入到更新队列,异步更新
                如果想更新完进行回调,可以采用Vue.nextTick(callback)
                ps:监听数据变更,改版dom的滚动条位置计算等,数据更新了,但是dom还没有
    5、组件方法
        5.1 method
            获取绑定的数据
                e.currentTarget.dataset.index (数据绑定在父元素的时候用这个)
                e.target.dataset.index (数据绑定在当前元素的时候用这个)
            event
            事件修饰符
                .stop
                .prevent
                .capture
                .self
                .once
            键值修饰符
                事件
                别名 自定义
                修饰键
        5.2 directive 自定义指令(不能直接操作dom,所以需要自定义指令)
            bind
            inserted
            update
            componentUpdated
            unbind
    
    6、生命周期
        beforeCreate
        √ created
        mount
        beforeMount
        mounted
        beforeUpdate
        updated 
        beforeDestory
        destroyed
    
五、状态管理 Vuex
    1、解决什么问题
        一份数据,很多个组件需要使用
        这些组件不仅仅是父子关系
    2、安装
        npm install vuex --save
    3、项目使用(全局store)
        import store from './store/index'
        
        new Vue({
          el: '#app',
          router,
          store,
          template: '',
          components: { App }
        })
    4、store介绍
        4.1 state
            类似组件的data
        4.2 getters
            类似computed计算属性
            setters: 没用过
        4.3 mutations
            类似method
            ps:mutations之间不能直接调用,不确定是否可以这么做
        
六、网络请求 vue-resource
    1、安装
    2、使用
        import VueResource from 'vue-resource'
        Vue.use(VueResource)
        ps:作为插件引入
    3、需要重新封装,跟常规的ajax请求不大一样
        3.1 api地址区分环境
        3.2 统一做鉴权等
    
七、语法注意
    1、var 改用let 或者const
    2、缩进 2个字符
    3、不能有;号
    4、空格
        function () {
        }
        // 注释文字
    
    

30分钟,快速在项目中使用git


编   写:袁 亮
时   间:2017-01-17
说   明:30分钟,快速在项目中使用git

一、账号环境
    1、https://gitlab.oneitfarm.com
        使用自己的企业邮箱注册自己的账号
    2、安装windows环境
        https://git-scm.com/downloads/guis
        \\192.168.0.18\运维网络硬盘\y袁亮\software\Git-2.8.1-64-bit.exe
        cmd下运行 git 配置 
            git config --global user.email ""
            git config --global user.name ""
    3、生成sshkey (https,安全证书,一台电脑一个)
        任意目录,右键,打开 Git GUI
        help => show sshkey => Generate Key
    4、在gitlab添加ssk key
        https://gitlab.oneitfarm.com/profile/keys
    
二、加入开发组 
    1、申请加入开发者 https://gitlab.oneitfarm.com/geek
    2、审核通过,并分配相应权限
    
三、导出项目代码
    1、本地无代码,从远程拉取【必须会】
        1.1 注意事项 
            使用https协议的,ssh的服务器没有开启
            所有跟远程代码库交互,都需要输入git账号和密码
            windows下,空项目一直clone不下来
        1.2 linux
            git clone https://gitlab.oneitfarm.com/geek/dealer.git yl
        1.3 windows
            空目录,右键Git Gui
            Clone Existing Respository
            ps:需要输3次账号密码,不知道是什么鬼
    2、本地有代码,关联到远程一个空代码库【了解即可】
        2.1 linux
            a. 创建本地仓库 git init
            b. git remote add 
        2.2 windows
            a. 创建本地仓库 Git Gui => Respository => New
            b. 将本地代码,提交到本地仓库 stage change => commit
            c. 关联远程代码仓库 Remote => Add
                origin
                https://gitlab.oneitfarm.com/geek/dealer.git
            d. 提交到远程代码仓库
                push 
    3、本地有代码,关联到远程一个非空代码库
        略
    
四、常规操作 【必须会】
    1、本地仓库 查看当前git状态
        1.1 git status (svn st)
        1.2 可以通过配置alish,使用git st    
    2、本地仓库 新增文件
        2.1 新增 
            git add application/controllers/Store.php
        2.2 提交到本地仓库
            git commit -m '增加store控制器' application/controllers/Store.php
    3、本地仓库 修改文件
        3.1 查看文件改动
            git diff webroot/index.php
        3.2 不想修改,恢复文件
            git checkout webroot/index.php
        3.3 文件改动存入缓存区
            git add webroot/index.php
        3.4 改错,不想保持,取消修改
            git reset webroot/index.php
            git checkout webroot/index.php
        3.4 提交修改
            git commit -m 'index.php代码' webroot/index.php
    4、本地仓库 删除文件
        4.1 本地仓库删除 
            git rm debug.php
        4.2 发现删了,撤销
            git reset HEAD debug.php
            git checkout debug.php
        4.3 确认删除,提交
            git commit -m '删除调试代码' debug.php
        4.3 提交之后发现删错了
            a. 查看 log
                git log 
            b. 找到删除前的版本,并回滚到那个版本
                git reset --hard {commit_id}
                将被删除的文件备份出来
            c. 查看所有的版本log,并找到要恢复的版本
                git reflog
            d. 恢复到最新版本
                 git reset --hard {commit_id}
            e.将备份出来的代码还原回去
                cp或者mv回来,然后add,commit
    5、查看文件版本记录
        git log webroot/index.php
    6、提交代码到远程仓库
        git push -u origin master
    7、从远程代码库拉取最新代码
        git pull 
    8、常用设置
        8.1 pull push 免去每次输账号密码
            git config --global credential.helper store
        8.2 颜色设置
            git config --global color.ui true
        8.3 常用alias
            git config --global alias.st 'status'
            git config --global alias.ci 'commit'
            git config --global alias.co 'checkout'
            git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
    9、忽略文件(日志,配置等不想要提交的文件)
        在项目文件下新建.gitignore文件
        文件中写入 /.idea/*  即忽略.idea文件 (!/.idea/echo.php 即不忽略.idea文件夹下的echo.php文件)
        *.txt 忽略txt类型的文件
        最后别忘了提交.gitignore文件
            
五、分支操作
    1、查看本地仓库分支及当前所在分支
        git branch 
    2、新建分支
        2.1 正常创建
            git branch dev
            git checkout dev
        2.2 命令合并
            git checkout -b dev
        2.3 从远程仓库创建分支
            a. 确保远程仓库有这个分支
            b. 更新本地仓库,确保本地知道远程仓库的分支 
                git remote update
                git fetch
                git remote show origin :查看远程分支
            c. 从远程分支中checkout一个分支到本地
                git checkout -b yl origin/yl
                ps:本地分支名可以起的跟远程分支名不一样,但不建议这么做,除非本地多个分支对应远程同一个分支
            d. 分支改动push到对应远程分支
                git push origin yl
    3、切换分支
        git checkout master
    4、删除分支
        git branch -d dev
        ps:如果删除未合并的分支,需要用-D参数,慎用,除非是写临时脚本的分支
    5、合并分支
        5.1 git merge dev 
        5.2 该命令是将dev分支合并到当前所在分支,因此需要先checkout到你所想要合并到的分支
            git checkout master
        5.3 冲突解决
            a. 手动修改冲突文件,然后提交
            b. 借助 mergetool (还没用过)
        5.3 查看分支合并情况
            git log --graph --pretty=oneline --abbrev-commit
    6、给绑定分支绑定远程分支
        git branch --set-upstream demo origin/yl
    7、拉取合并指定指定远程仓库的指定分支
        git pull  
        git pull origin yl

六、GitLab Flow 工作流
    1、参考文档
        http://www.ruanyifeng.com/blog/2015/12/git-workflow.html
    2、我们采用的方式
        Gitlab flow
        版本发布
    
七、远程仓库使用
    1、添加远程仓库
        git remote add  
        shortname默认是origin
    2、查看远程仓库信息
        git remote :查看shortname
        git remote -v :查看完整信息
    3、拉取远程仓库的信息
        git fetch  :也可以使用,默认是origin
        ps:fetch只会拉取数据,但并不合并,pull是fetch之后会自动合并git merge
    4、推送到远程仓库
        4.1 git push origin master
        4.2 将本地master分支推送到origin远程仓库中对应的分支
        4.3 如果origin仓库里对应的分支已经有人改过,必须先pull下来,然后才能推送
        4.4 master分支推送到origin仓库的具体哪个分支,是由之前创建分支的时候决定的,并不是根据分支名来
            如果两个名字不一样,很容易出现一些看起来莫名其妙的问题,所以不要干这个事
    5、查看远程仓库
        git remote show [remote-name] 

八、标签tag (对应之前的release)
    1、本地仓库 查看所有标签
        1.1 git tag
        1.1 git tag -l '匹配规则,可以写正则'
        1.2 以标签名排序,不以创建时间
    2、本地仓库 创建标签
        2.1 git tag -a v1.0.0 -m '标签注释'
        2.2 不输入-m,在运行编辑器里可以更方便的写各种备注
        2.3 不允许打轻量标签,除非是本地测试用
    3、本地仓库 查看标签信息
        git show v.1.0.0
    4、将标签推送到远程仓库
        4.1 git push origin [tagname]
        4.2 多个标签,也单个单个推,不允许一次性把所有标签推上去
    5、从标签中检出新的分支
        5.1 git checkout -b fix-v2.0.0 v2.0.0
        5.2 类似分支的创建,如果本地没有v2.0.0这个标签,需要先从远程仓库pull或者fetch下来
    6、修复线上tag两种办法
        
        
参考文档:
    1、Git教程
        http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000
    2、Git 工作流程
        http://www.ruanyifeng.com/blog/2015/12/git-workflow.html
    3、Git分支管理策略
        http://www.ruanyifeng.com/blog/2012/07/git.html
    4、Git 使用规范流程
        http://www.ruanyifeng.com/blog/2015/08/git-use-process.html
    5、git 文档
        https://git-scm.com/book/zh/v2/
    6、Git可视化极简易教程 — Git GUI使用方法 
        http://www.runoob.com/w3cnote/git-gui-window.html
    7、GitLab Flow的使用
        https://www.15yan.com/story/6yueHxcgD9Z/
        https://about.gitlab.com/2014/09/29/gitlab-flow/
    8、如何使用gitlab的flow以及代码review
        http://mojito515.github.io/blog/2016/03/09/ru-he-shi-yong-gitlabde-flowyi-ji-dai-ma-review/
    9、The 11 Rules of GitLab Flow
        https://about.gitlab.com/2016/07/27/the-11-rules-of-gitlab-flow/
    10、使用git、git-flow与gitlab工作
        http://blog.2baxb.me/archives/736
    11、GitLab的Pull Request工作流
        http://www.jianshu.com/p/6bcd082101c1
    12、常用 Git 命令清单
        http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html
        
        

6位数支付密码安全使用


编   写:袁 亮
时   间:2017-02-13
说   明:6位数支付密码安全使用

一、目的
    1、用户可以设置6位数字的支付密码用来使用自己的账号余额
    2、确保用户的支付密码使用、存储安全
    
二、业务场景描述
    1、设置支付密码
        在相应的业务流程中,用户设置自己的支付密码
    2、使用支付密码
        在支付、提现等地方输入密码进行操作
    3、重置支付密码
        忘记密码的情况下,提供重置密码的流程
    
三、用户密码安全分类
    1、流程逻辑漏洞
        1.1 平行权限
            比如仅仅在展示页面验证了权限,但实际操作的ajax请求等未做验证之类的
            或者验证之后,存储了一个已验证通过标识,然后通过这个标识去做后续操作
        1.2 业务逻辑漏洞
            比如找回密码,直接将原密码通过邮件等方式发送给了用户
            比如找回密码的token,没有绑定用户,导致可以修改任意用户
                或者没有过期时间,或者使用过之后还能再用
    2、明文密码
        2.1 http传输
            劫持、监听、篡改、xss攻击等
        2.2 GET传输
            url中会有密码,从而导致很多地方会泄露,比如统计代码、url日志等等
        2.3 log日志记录
            开发过程中,有人会将这个数据写入到日志里,日志泄露等导致密码泄露
        2.4 客户端存储
            比较菜的情况下,会把密码这种东西写在cookie里...
            移动app中把密码记录在app里
        2.5 数据库明文存储
            内部人员能看到,后台、数据库等等
            或者api里,读取所有字段等,导致把密码泄露
            数据被人拖库或者sql注入直接显示在页面上等等
    3、撞库攻击
        3.1 弱密码
            常用弱密码库,1000个不到
        3.2 响应时间差攻击
            不同错误密码判断所需时间不同,导致跨域逐步猜测
        3.3 网上已泄露的密码库,直接撞库攻击
            多次大规模安全事故,已经有极其庞大的密码库被公开
    4、应用层攻击
        4.1 sql注入
            构造特殊参数,直接绕过判断条件
        4.2 webshell
            通过webshell拦截密码或者获取到对应的数据库数据
        4.3 服务器入侵
    5、拖库后,从hash值获取对应明文
        5.1 反向查表
        5.2 彩虹表
            优化存储空间之后的一种反向查表攻击
        5.3 暴力破解
            a. 根据hash值和密码设置规则,强行遍历所有组合的所有hash,比对已有hash是否匹配
            b. 单个 GPU 上以每秒 36.5 亿次计算的速率破解 MD5 的哈希值
                以每秒 13.6 亿次计算的速度破解 SHA-1 的哈希值
                而且很多hash算法还能被硬件加速
                
四、实施方案
    1、第一次设置支付密码
        1.1 业务流程要求
            必须登陆状态
            用户必须绑定过手机号(不然的话找回密码就不行了)
        1.2 开发注意事项
            必须https,以POST形式传输数据
            ua必须是正常的
            不能以任何形式将密码记录在服务器硬盘上,比如log日志等
            不允许存储在本地客户端,比如cookie,本地存储
        1.3 密码存储
            使用password_hash方法,将密码进行hash运算,结果存储到数据库中
            记录用户设置环境的log
                ua,x-forword-for,访问url、设置时间等等
    2、使用支付密码
        2.1 业务流程要求
            必须登陆状态
            账号需要未冻结
        2.2 开发注意事项
            必须https,POST传输
            ua必须是正常的
            支付密码必须要跟所需操作同时发送过期,内部调用验证支付密码,不允许分步来做
            支付密码后期可能会替换为指纹
        2.3 验证逻辑
            验证连续错误次数是否达到上限
            是否频繁操作,频率限制
            每天最大验证次数超出上限,异常报警(内部限制上限)
            获取用户对应password_hash,验证是否正确
            记录日志:登陆信息及是否正确等信息
            正确
                验证数据库里存储的hash是否是用最新的hash生成方式生成,如果不是,需要刷新重新写入
            错误
                错误提示
    3、重置支付密码
        3.1 业务流程要求
            用户登陆
            只能使用之前绑定的手机号发送短信验证码
                ps:现在其实是可以随时绑定新的手机号,有逻辑上的漏洞
        3.2 开发注意事项
            https,POST数据
            验证码和新密码必须在同一次请求里发送,不允许分开
        3.3 重置逻辑
            a. 判断条件
                登陆判断
                手机号是否是用户绑定的手机号
                短信验证码是否正确
                密码是否合法
            b. 处理逻辑
                生成password_hash
                记录修改记录
                更新用户password_hash
        ps:如果是邮箱形式的密码修改,注意事项
            发送token
            token不能有任何的用户信息
            token必须有失效条件
                发送了新的,旧的就必须失效
                有效期
                使用过之后就失效            
                不要通过email发送用户的新密码

五、知识拓展,了解即可
    1、散列hash
        1.1 内容摘要算法
        1.2 加密和hash的区别
        1.3 hash碰撞
            hash长度固定,而且集合比内容集合小,所以存在内容不一样,hash值一样的情况
        1.4 hash函数和加密hash函数的区别
        1.5 慢速hash函数
        1.6 盐值
    2、hash破解办法
        反向查表
        彩虹表
        暴力破解
    3、撞库攻击
    4、安全分类
        浏览器安全
            xss攻击
            csrf
            点击劫持
            H5
        应用服务器安全
            sql注入
            文件上传
            会话劫持
            访问控制
            web框架安全
            DDOS攻击
            PHP语言安全
            webSERVER 配置安全
        运维安全
            服务器入侵
            防火墙
            开源产品安全设置
                redis、memcache、mongodb等等

六、参考文档
    OWASP
        https://www.owasp.org/index.php/Main_Page
    Salted Password Hashing - Doing it Right
        https://crackstation.net/hashing-security.htm
    如何安全的存储用户的密码
        http://www.freebuf.com/articles/web/28527.html
    更新后的 PHP: 现代 PHP 中的密码安全性
        http://www.ibm.com/developerworks/cn/web/wa-php-renewed_2/
    浅谈密码存储安全
        https://my.oschina.net/hjh188/blog/491666
    用户密码加密存储十问十答,一文说透密码安全存储
        http://www.cnblogs.com/xinzhao/p/6035847.html   
    Dropbox是如何安全地存储用户密码的
        http://www.infoq.com/cn/news/2016/12/How-Dropbox-securely-passwords
    Portable PHP password hashing framework
        http://www.openwall.com/phpass/
    hash_values
        http://msdn.microsoft.com/en-us/library/92f9ye3s.aspx#hash_values
    How do you use bcrypt for hashing passwords in PHP?
        http://stackoverflow.com/questions/4795385/how-do-you-use-bcrypt-for-hashing-passwords-in-php
    PHP处理密码的几种方式
        https://segmentfault.com/a/1190000003024932
    密码散列安全
        http://php.net/manual/zh/faq.passwords.php

开发流程


编   写:袁 亮
时   间:2017-02-10
说   明:开发流程

一、需求分析
    1、需求文档
    2、会议需求讨论、问题沟通
    
二、原型、设计图
    1、原型
    2、设计图
    3、前端人员提前参与
    
三、技术方案
    1、技术方案确认
    2、流程明确
    3、数据字典设计
    4、时间预估、排期、人员安排
    
四、具体开发文档
    1、各开发小组编写
    2、功能细分
        小组分工
        完成时间点
    3、问题记录
        业务上不清楚的
        实现方案不清楚的
        流程不确定的
        业务后续可能扩展
    4、接口列表
        跟其他组对接,接口定义、分配
    5、开发小组内测问题列表
    
五、完整测试
    1、团队相关人员都需要参与,包括产品、运营、设计、前端等
    2、维护统一的bug列表
    3、每个bug各开发认领修复
    
六、打包上线
    1、合并打包
    2、线上测试、回滚
    
七、文档
    1、数据字典入库
    2、apidoc文档编写
    

在postman中调用自定义签名方式的API


编   写:袁 亮
时   间:2017-02-09
说   明:在postman中自定义签名方式调用接口

一、目的
    1、电商项目内部api接口使用的签名方式导致在postman中不能使用
        需要在postman中,自行实现签名方式以方便测试API接口
    2、接口地址
        https://api.shop.ci123.com/apidoc/
    
二、实现原理
    1、在postman实际调用接口前,可以执行自定义js,从而实现数据签名
    2、自定义JS可以获取到请求参数、链接参数,并且可以自定义变量

三、实现过程
    1、增加链接参数 params
        appid:{{appid}}
    2、接口post参数增加
        expire:{{expire}}
        mdstr:{{mdstr}}
    3、添加预执行脚本 Pre-request script
        var appid = '10101';
        var appsercet = '8e2160ec2b07f1faca9055be530bf09d';

        // 定义appid
        postman.setEnvironmentVariable("appid", appid);

        // 定义时间戳
        var expire = new Date().getTime();
        postman.setGlobalVariable("expire", expire);

        // 数据签名
        var data = [];
        jQuery.each(request.data, function(key, value){
            if (key == 'expire') { // request里存储的是定义的值,而不是我们赋的值,需要单独处理
                value = expire;
            }
            if (key != 'mdstr') {
                data.push(key+'='+value);
            }
        });
        data.sort();
        var str = data.join('&')+appsercet;
        var mdstr = CryptoJS.MD5(str).toString().toLowerCase();
        postman.setGlobalVariable("mdstr", mdstr);
    
四、环境切换
    1、变量
        环境变量:EnvironmentVariable
            在整个environment内都可以用
            ps:在预执行脚本中,需要用environment.变量名来获取,不能执行获取到
        全局变量:GlobalVariable
            可以在任意环境下使用
            ps:预执行脚本中定义的变量并不能在url、params使用
                原因是因为拼接在预执行脚本之前
                单在body里又是可以用的,数据组装在预执行脚本代码之后
        自定义变量:
            仅能在预执行脚本中用
    2、环境管理
        2.1 可以将不同环境的变量定义在环境变量中
            比如测试机host,比如appid和appsecret等
        2.2 在url、params、body中的数据,预执行脚本等地方使用
    3、接口调用
        3.1 选择环境
        3.2 接口地址、参数等使用环境变量{{变量名}}
        3.3 添加接口特定参数
    4、添加预执行脚本
        // 定义时间戳
        var expire = new Date().getTime();
        postman.setGlobalVariable("expire", expire);

        // 数据签名
        var data = [];
        jQuery.each(request.data, function(key, value){
            if (key == 'expire') { // request里存储的是定义的值,而不是我们赋的值,需要单独处理
                value = expire;
            }
            if (key != 'mdstr') {
                data.push(key+'='+value);
            }
        });
        data.sort();
        var str = data.join('&')+environment.appsercet;
        var mdstr = CryptoJS.MD5(str).toString().toLowerCase();
        postman.setGlobalVariable("mdstr", mdstr);
    
    
    

用户系统演进

用户系统演进.ppt

编   写:袁 亮
时   间:2016-12-21
说   明:用户系统演进

一、用户系统限制因素
    1、使用域名
        单个域名
        多个域名
    2、使用系统是单服务器还是多服务器
    3、使用域名是否属于同一个域名的不同子域名
    4、系统访问环境
        PC浏览器
        是否兼容IE浏览器
        是否兼容手机浏览器
    5、用户数据库是否唯一
        单一用户数据库
        多个用户数据库
        
二、单用户中心,单域名
    1、条件限制
        1.1 单个域名
        1.2 单一用户数据库
    2、实现方案
        2.1 session
            磁盘IO 
            多服务器session共享
        2.2 cookie
            域名,端口,路径,cookie名
            数据签名
            大小限制
            敏感信息
    3、其他
        3.1 可以有多种登陆方式
        3.2 可以接入很多种第三方登陆
        
三、单用户中心,单个根域名
    1、条件限制
        1.1 单个用户数据库
        1.2 多个域名同属于某个根域名
    2、实现方案
        2.1 cookie共享 (育儿网)
            a. cookie设置在根域名
            b. 所有子域名都可以正常读取并验证签名
            c. 不可扩展,安全性无保障
        2.2 token形式 (共享session机制的变种)
            a. cookie设置在根域名
            b. 子域名读取到cookie之后,调用用户中心接口获取用户数据
            c. 将用户数据写入当前域名下
            
四、单用户中心,多个根域名
    1、条件限制
        1.1 单个用户数据库
    2、实现方案
        2.1 单点登陆 jsonp方式跨域 (淘宝)
            a. 统一的登陆,查收ticket
            b. jsonp方式将ticket循环传递给所有业务
            c. 业务域名根据ticket获取用户信息设置登陆
            d. 退出同样方式处理
            缺点:
                ios下,浏览器默认禁止第三方域名cookie设置,直接歇菜
        2.2 单点登陆 cas方式 (新浪)
            a. 通过jsonp+ajax+iframe的方式,在各个子域名框用户中心登陆
            b. 
            缺点:手机浏览器对iframe支持的很差
        2.3 服务端ticket形式,jsonp形式单点登录的变种
        
五、多用户中心
    1、条件限制
        无
    2、实现方案
        2.1 单域名或者多根域名跨域同三和四
    3、额外增加处理
        3.1 统一跳转地址
        3.2 用户聚合统一
        3.3 平台信息维护
        3.4 vtoken登录