stf二次开发--初级篇

背景

  项目有一个web系统,需要接入STF.但是直接访问STF网站的首页,会跳转到STF登录页面。现在希望绕过登录操作。我使用的是STF的mock模式
安装说明


  我刚开始是在TesterHome上看的如何安装。但是,我是希望修改STF的源码的。我没有看到TesterHome有类似帖子的介绍。我把这个部分说一下。首先安装部分,还是进openSTF的首页,查看标准的安装过程。
然后,在下载phantomjs的时候可能会非常慢,我推荐使用淘宝镜像:

npm install phantomjs --phantomjs_cdnurl=https://npm.taobao.org/dist/phantomjs

  将依赖包安装成功之后,下载stf源码,然后执行命令

npm install && npm link

  如果你修改了stf源码,关闭当前运行的stf,执行命令gulp clean && gulp webpack:build && stf local,修改会生效

  调试方案的话,推荐直接打log日志,代码如下所示

var logger = require('../../../util/logger')
var log = logger.createLogger('guess the client')
log.info('jwt is ')

  require() 的路径是-- 包含log打印日志的文件相对于'/yourHomeDir/stf-2.1.0/lib/util/logger.js'的路径
然后,控制台就可以看到了打印的消息

安装小tips

  在使用npm时,可以使用淘宝的镜像。淘宝镜像以及使用方法
STF框架


  STF是基于node.js,它的中间件使用的是Express框架,前端使用angular框架,如果想要二次开发,这2个框架的基本知识最好熟悉一下。
后端拦截器


  写过Web程序的都应该知道,会存在前端拦截器和后端拦截器。首先找到后端的拦截器,再找的前端拦截器。说一下思路。之前看这篇文章,在/res/auth/mock,目录下找到了如下的代码段

 $scope.submit = function() {
    var data = {
      name: $scope.signin.username.$modelValue
      , email: $scope.signin.email.$modelValue
    }
    $scope.invalid = false
    $http.post('/auth/api/v1/mock', data)
      .success(function(response) {
        $scope.error = null
        location.replace(response.redirect)
      })
      .error(function(response) {
        switch (response.error) {
          case 'ValidationError':
            $scope.error = {
              $invalid: true
            }
            break
          case 'InvalidCredentialsError':
            $scope.error = {
              $incorrect: true
            }
            break
          default:
            $scope.error = {
              $server: true
            }
            break
        }
      })
  }

  这段代码重要是$http.post('/auth/api/v1/mock', data), 我们可以猜到这段代码的意思,是向后端的某个接口,发送用户名和密码。如果我们对项目STF全局搜索关键字"/auth/api/v1/mock", 看到后端对这个接口的处理的代码。果然,发现了文件"/stf-2.1.0/lib/units/auth/mock.js"的代码段

app.post('/auth/api/v1/mock', function(req, res) {
    var log = logger.createLogger('auth-mock')
    log.setLocalIdentifier(req.ip)
    switch (req.accepts(['json'])) {
      case 'json':
        requtil.validate(req, function() {
            req.checkBody('name').notEmpty()
            req.checkBody('email').isEmail()
          })
          .then(function() {
            log.info('Authenticated "%s"', req.body.email)
            var token = jwtutil.encode({
              payload: {
                email: req.body.email
              , name: req.body.name
              }
            , secret: options.secret
            , header: {
                exp: Date.now() + 24 * 3600
              }
            })
            log.info('appurl is  "%s", token is  "%s"',options.appUrl, token)
            log.info('redirect url  is  "%s"',                  urlutil.addParams(options.appUrl, {
              jwt: token
            }))

            res.status(200)
              .json({
                success: true
              , redirect: urlutil.addParams(options.appUrl, {
                  jwt: token
                })
              })
          })
          .catch(requtil.ValidationError, function(err) {
            res.status(400)
              .json({
                success: false
              , error: 'ValidationError'
              , validationErrors: err.errors
              })
          })
          .catch(function(err) {
            log.error('Unexpected error', err.stack)
            res.status(500)
              .json({
                success: false
              , error: 'ServerError'
              })
          })
        break
      default:
        res.send(406)
        break
    }
  })

  这个代码段重要的点是urlutil.addParams(options.appUrl, {jwt: token}), 将token打印处理,看输出的到底是什么值,发现值如下所示

jwt=eyJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6InNoZXJhbmp1bkB3ZWlkaWFuLmNvbSIsIm5hbWUiOiJzaGVyYW5qdW4ifQ.w9JJtvHr32q71BRmbu4c0w9ezwD51P8v-bEgiRoW6qU

  我们打开STF的首页,跳转到登录页面,在首页增加上面的参数。可以看到,无需登录,我们就进STF的首页。那么从外部系统进入免登进入STF的方案就可以出来了:

  在mock.js中增加一个新的接口,get方法,接受参数值username,返回jwt。我们仿造上面函数,代码如下所示:

  app.get('/auth/api/fromzeus/mock', function(req, res) {
    var log = logger.createLogger('auth-mock')
    log.setLocalIdentifier(req.ip)
    log.info('Authenticated "%s"', req.query.name)
    log.info('Authenticated ip  is "%s"', req.ip)

    var user = new Buffer(req.query.name, 'base64').toString('ascii')
    user = user.trim()
    log.info('base64解码的内容 "%s"',user)
    if (!user) {
      res.status(400)
        .json({
          success: false
          , error: 'ValidationError'
          , validationErrors: err.errors
        })
    }

    log.info('secrest is  "%s"',options.secret)
    //todo:异常处理
    var token = jwtutil.encode({
      payload: {
        email: user + "@126.com"
        , name: user
      }
      , secret: options.secret
      // , header: {
      //   exp: Date.now() + 24 * 3600
      // }
    })
    log.info('appurl is  "%s", token is  "%s"',options.appUrl, token)
    log.info('token is  "%s"', token)
    res.status(200)
      .json({
        success: true
        , token: token
      })
  })

如何在关闭浏览器后,立即释放设备

通过捕获浏览器的关闭事件,来决定是否释放设备。这个方案当初调研时因为不可用,所以直接pass掉了。本质上之所以有这个解决方案的原因是: 在关闭浏览器后,能有一个入口,释放设备。那么,方案来了:
1.我们有两个页面,第一个设备列表页,第二个是设备调试页面(也就是stf的嵌入页面)。即使设备调试页面被关闭,它的状态还是调试中,我们可以根据设备列表页,来释放设备。
a.设备列表页

image.png

b.设备调试页


stf二次开发--初级篇_第1张图片
image.png

参考链接

安装npm
淘宝镜像
express框架
angular框架
express路由

你可能感兴趣的:(stf二次开发--初级篇)