stf二次开发
前几天装了一下stf环境 ,mac环境搭建stf
环境搭建还是比较简单的。这个平台登陆的时候是没有限制的,只要输入个名称和邮箱就可以登陆。打算修改一下,改成公司内部账号登陆,下面来撸一撸代码。
这张图片是在网上找的,根据这个区分出来了前端和后端代码。

stf前端使用的是angularjs语言开发的(测试小白,以前没有听过?),后端是nodejs(对于使用Java的我来说,这两个语言有点懵)没办法现学现卖,先去看看基本语法,然后在结合stf源码慢慢啃吧。
打开stf地址是http://192.168.110.18:7100/auth/mock/
在res路径下面找到了前端代码,修改.pug文件可以改变前端页面渲染。
先打开signin.pug把邮箱和name换一下,把name输入框换成password输入框。
.login2(ng-controller='SignInCtrl').login-wrappera(href='./')img(width='200', height='85', src='/static/logo/exports/STF-512.png', title='STF')form(name='signin', novalidate, ng-submit='submit()').alert.alert-danger(ng-show='error')span(ng-show='error.$invalid', translate) Check errors belowspan(ng-show='error.$incorrect', translate) Incorrect login detailsspan(ng-show='error.$server', translate) Server error. Check log output..form-group.input-groupspan.input-group-addoni.fa.fa-envelopeinput.form-control(ng-model='email', name='email', required, type='email', placeholder='E-mail',autocorrect='off', autocapitalize='off', spellcheck='false', autocomplete='section-login email').alert.alert-warning(ng-show='signin.email.$dirty && signin.email.$invalid')span(ng-show='signin.email.$error.email', translate) Please enter a valid emailspan(ng-show='signin.email.$error.required', translate) Please enter your email.form-group.input-groupspan.input-group-addoni.fa.fa-userinput.form-control(ng-model='pwd', name='pwd', required, type='password', placeholder='Password',autocorrect='off', autocapitalize='off', spellcheck='false', autocomplete='section-login username').alert.alert-warning(ng-show='signin.pwd.$dirty && signin.pwd.$invalid')span(translate) Please enter your passwordinput.btn.btn-lg.btn-primary.btn-block(type='submit', value='Log In')
再找到前端控制器signin-controller.js,修改之前的name为pwd
module.exports = function SignInCtrl($scope, $http) {$scope.error = null//获取前端页面提交的用户名和email$scope.submit = function() {var data = {pwd: $scope.signin.pwd.$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}breakcase 'InvalidCredentialsError':$scope.error = {$incorrect: true}breakdefault:$scope.error = {$server: true}break}})}
}

再找到后端登录接口,打开mock.js
var http = require('http')var express = require('express')
var validator = require('express-validator')
var cookieSession = require('cookie-session')
var bodyParser = require('body-parser')
var serveStatic = require('serve-static')
var csrf = require('csurf')
var Promise = require('bluebird')
var basicAuth = require('basic-auth')var logger = require('../../util/logger')
var requtil = require('../../util/requtil')
var jwtutil = require('../../util/jwtutil')
var pathutil = require('../../util/pathutil')
var urlutil = require('../../util/urlutil')
var lifecycle = require('../../util/lifecycle')module.exports = function(options) {var log = logger.createLogger('auth-mock')var app = express()var server = Promise.promisifyAll(http.createServer(app))lifecycle.observe(function() {log.info('Waiting for client connections to end')return server.closeAsync().catch(function() {// Okay})})// 这里没有用到// BasicAuth Middlewarevar basicAuthMiddleware = function(req, res, next) {function unauthorized(res) {res.set('WWW-Authenticate', 'Basic realm=Authorization Required')return res.send(401)}var user = basicAuth(req)if (!user || !user.name || !user.pass) {return unauthorized(res)}if (user.name === options.mock.basicAuth.username &&user.pass === options.mock.basicAuth.password) {return next()}else {return unauthorized(res)}}app.set('view engine', 'pug')app.set('views', pathutil.resource('auth/mock/views'))app.set('strict routing', true)app.set('case sensitive routing', true)app.use(cookieSession({name: options.ssid, keys: [options.secret]}))app.use(bodyParser.json())app.use(csrf())app.use(validator())app.use('/static/bower_components',serveStatic(pathutil.resource('bower_components')))app.use('/static/auth/mock', serveStatic(pathutil.resource('auth/mock')))app.use(function(req, res, next) {res.cookie('XSRF-TOKEN', req.csrfToken())next()})if (options.mock.useBasicAuth) {app.use(basicAuthMiddleware)}// 页面请求为ip+端口,重定向到登陆页面app.get('/', function(req, res) {res.redirect('/auth/mock/')})// 页面请求为ip+端口/auth/mock/,打开登陆页面app.get('/auth/mock/', function(req, res) {res.render('index')})// 前端请求登陆接口,验证用户名密码是否正确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('pwd').notEmpty()req.checkBody('email').isEmail()}).then(function() {log.info('Authenticated "%s"', req.body.email)var token = jwtutil.encode({payload: {email: req.body.email, pwd: req.body.pwd}, secret: options.secret, header: {exp: Date.now() + 24 * 3600}})//下面一直到########结束都是新添加的var Data = {account: req.body.email, password: req.body.pwd}var postData = JSON.stringify(Data)var Options = {hostname: 'www.baidu.com' //这里是公司oa的登录接口, port: 80, path: '/api/login/password', method: 'post', headers: {'Content-Type': 'application/json;charset=UTF-8'}}var Request = http.request(Options, function(response) {var responseString = ''response.on('data', function(chun) {responseString += chun})response.on('end', function() {var resultObject = JSON.parse(responseString)if (resultObject.status === 200) {res.status(200).json({success: true, redirect: urlutil.addParams(options.appUrl, {jwt: token})})}else {res.status(400).json({success: false, error: 'ValidationError', validationErrors: resultObject.msg})}})}) //################Request.on('error', function(err) {log.error(err)})Request.write(postData)Request.end()}).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'})})breakdefault:res.send(406)break}})server.listen(options.port)log.info('Listening on port %d', options.port)
}

再找到修改数据库的代码auth.js
var jwtutil = require('../../../util/jwtutil')
var urlutil = require('../../../util/urlutil')var dbapi = require('../../../db/api')module.exports = function(options) {return function(req, res, next) {if (req.query.jwt) {// Coming from auth clientvar data = jwtutil.decode(req.query.jwt, options.secret)var redir = urlutil.removeParam(req.url, 'jwt')if (data) {// Redirect once to get rid of the tokendbapi.saveUserAfterLogin({pwd: data.pwd //这里是修改过的, email: data.email, ip: req.ip}).then(function() {req.session.jwt = datares.redirect(redir)}).catch(next)}else {// Invalid token, forward to auth clientres.redirect(options.authUrl)}}else if (req.session && req.session.jwt) {dbapi.loadUser(req.session.jwt.email).then(function(user) {if (user) {// Continue existing sessionreq.user = usernext()}else {// We no longer have the user in the databaseres.redirect(options.authUrl)}}).catch(next)}else {// No session, forward to auth clientres.redirect(options.authUrl)}}
}

最后找到执行数据库语句操作的代码api.js
var r = require('rethinkdb')
var util = require('util')var db = require('./')
var wireutil = require('../wire/util')var dbapi = Object.create(null)dbapi.DuplicateSecondaryIndexError = function DuplicateSecondaryIndexError() {Error.call(this)this.name = 'DuplicateSecondaryIndexError'Error.captureStackTrace(this, DuplicateSecondaryIndexError)
}util.inherits(dbapi.DuplicateSecondaryIndexError, Error)dbapi.close = function(options) {return db.close(options)
}dbapi.saveUserAfterLogin = function(user) {return db.run(r.table('users').get(user.email).update({name: user.email.split('@')[0] //这里是修改过的, ip: user.ip, lastLoggedInAt: r.now()})).then(function(stats) {if (stats.skipped) {return db.run(r.table('users').insert({email: user.email, name: user.email.split('@')[0] //这里是修改过的, ip: user.ip, group: wireutil.makePrivateChannel(), lastLoggedInAt: r.now(), createdAt: r.now(), forwards: [], settings: {}}))}return stats})
}dbapi.loadUser = function(email) {return db.run(r.table('users').get(email))
}dbapi.updateUserSettings = function(email, changes) {return db.run(r.table('users').get(email).update({settings: changes}))
}dbapi.resetUserSettings = function(email) {return db.run(r.table('users').get(email).update({settings: r.literal({})}))
}dbapi.insertUserAdbKey = function(email, key) {return db.run(r.table('users').get(email).update({adbKeys: r.row('adbKeys').default([]).append({title: key.title, fingerprint: key.fingerprint})}))
}dbapi.deleteUserAdbKey = function(email, fingerprint) {return db.run(r.table('users').get(email).update({adbKeys: r.row('adbKeys').default([]).filter(function(key) {return key('fingerprint').ne(fingerprint)})}))
}dbapi.lookupUsersByAdbKey = function(fingerprint) {return db.run(r.table('users').getAll(fingerprint, {index: 'adbKeys'}))
}dbapi.lookupUserByAdbFingerprint = function(fingerprint) {return db.run(r.table('users').getAll(fingerprint, {index: 'adbKeys'}).pluck('email', 'name', 'group')).then(function(cursor) {return cursor.toArray()}).then(function(groups) {switch (groups.length) {case 1:return groups[0]case 0:return nulldefault:throw new Error('Found multiple users for same ADB fingerprint')}})
}dbapi.lookupUserByVncAuthResponse = function(response, serial) {return db.run(r.table('vncauth').getAll([response, serial], {index: 'responsePerDevice'}).eqJoin('userId', r.table('users'))('right').pluck('email', 'name', 'group')).then(function(cursor) {return cursor.toArray()}).then(function(groups) {switch (groups.length) {case 1:return groups[0]case 0:return nulldefault:throw new Error('Found multiple users with the same VNC response')}})
}dbapi.loadUserDevices = function(email) {return db.run(r.table('devices').getAll(email, {index: 'owner'}))
}dbapi.saveDeviceLog = function(serial, entry) {return db.run(r.table('logs').insert({serial: serial, timestamp: r.epochTime(entry.timestamp), priority: entry.priority, tag: entry.tag, pid: entry.pid, message: entry.message}, {durability: 'soft'}))
}dbapi.saveDeviceInitialState = function(serial, device) {var data = {present: false, presenceChangedAt: r.now(), provider: device.provider, owner: null, status: device.status, statusChangedAt: r.now(), ready: false, reverseForwards: [], remoteConnect: false, remoteConnectUrl: null, usage: null}return db.run(r.table('devices').get(serial).update(data)).then(function(stats) {if (stats.skipped) {data.serial = serialdata.createdAt = r.now()return db.run(r.table('devices').insert(data))}return stats})
}dbapi.setDeviceConnectUrl = function(serial, url) {return db.run(r.table('devices').get(serial).update({remoteConnectUrl: url, remoteConnect: true}))
}dbapi.unsetDeviceConnectUrl = function(serial) {return db.run(r.table('devices').get(serial).update({remoteConnectUrl: null, remoteConnect: false}))
}dbapi.saveDeviceStatus = function(serial, status) {return db.run(r.table('devices').get(serial).update({status: status, statusChangedAt: r.now()}))
}dbapi.setDeviceOwner = function(serial, owner) {return db.run(r.table('devices').get(serial).update({owner: owner}))
}dbapi.unsetDeviceOwner = function(serial) {return db.run(r.table('devices').get(serial).update({owner: null}))
}dbapi.setDevicePresent = function(serial) {return db.run(r.table('devices').get(serial).update({present: true, presenceChangedAt: r.now()}))
}dbapi.setDeviceAbsent = function(serial) {return db.run(r.table('devices').get(serial).update({present: false, presenceChangedAt: r.now()}))
}dbapi.setDeviceUsage = function(serial, usage) {return db.run(r.table('devices').get(serial).update({usage: usage, usageChangedAt: r.now()}))
}dbapi.unsetDeviceUsage = function(serial) {return db.run(r.table('devices').get(serial).update({usage: null, usageChangedAt: r.now()}))
}dbapi.setDeviceAirplaneMode = function(serial, enabled) {return db.run(r.table('devices').get(serial).update({airplaneMode: enabled}))
}dbapi.setDeviceBattery = function(serial, battery) {return db.run(r.table('devices').get(serial).update({battery: {status: battery.status, health: battery.health, source: battery.source, level: battery.level, scale: battery.scale, temp: battery.temp, voltage: battery.voltage}}, {durability: 'soft'}))
}dbapi.setDeviceBrowser = function(serial, browser) {return db.run(r.table('devices').get(serial).update({browser: {selected: browser.selected, apps: browser.apps}}))
}dbapi.setDeviceConnectivity = function(serial, connectivity) {return db.run(r.table('devices').get(serial).update({network: {connected: connectivity.connected, type: connectivity.type, subtype: connectivity.subtype, failover: !!connectivity.failover, roaming: !!connectivity.roaming}}))
}dbapi.setDevicePhoneState = function(serial, state) {return db.run(r.table('devices').get(serial).update({network: {state: state.state, manual: state.manual, operator: state.operator}}))
}dbapi.setDeviceRotation = function(serial, rotation) {return db.run(r.table('devices').get(serial).update({display: {rotation: rotation}}))
}dbapi.setDeviceNote = function(serial, note) {return db.run(r.table('devices').get(serial).update({notes: note}))
}dbapi.setDeviceReverseForwards = function(serial, forwards) {return db.run(r.table('devices').get(serial).update({reverseForwards: forwards}))
}dbapi.setDeviceReady = function(serial, channel) {return db.run(r.table('devices').get(serial).update({channel: channel, ready: true, owner: null, reverseForwards: []}))
}dbapi.saveDeviceIdentity = function(serial, identity) {return db.run(r.table('devices').get(serial).update({platform: identity.platform, manufacturer: identity.manufacturer, operator: identity.operator, model: identity.model, version: identity.version, abi: identity.abi, sdk: identity.sdk, display: identity.display, phone: identity.phone, product: identity.product, cpuPlatform: identity.cpuPlatform, openGLESVersion: identity.openGLESVersion}))
}dbapi.loadDevices = function() {return db.run(r.table('devices'))
}dbapi.loadPresentDevices = function() {return db.run(r.table('devices').getAll(true, {index: 'present'}))
}dbapi.loadDevice = function(serial) {return db.run(r.table('devices').get(serial))
}dbapi.saveUserAccessToken = function(email, token) {return db.run(r.table('accessTokens').insert({email: email, id: token.id, title: token.title, jwt: token.jwt}))
}dbapi.removeUserAccessToken = function(email, title) {return db.run(r.table('accessTokens').getAll(email, {index: 'email'}).filter({title: title}).delete())
}dbapi.loadAccessTokens = function(email) {return db.run(r.table('accessTokens').getAll(email, {index: 'email'}))
}dbapi.loadAccessToken = function(id) {return db.run(r.table('accessTokens').get(id))
}module.exports = dbapi

这样就可以使用公司内部的账号密码登录了。

加班写的,思维有点乱,有时间整理一下。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
