云服务器内容精选

  • 操作步骤 “用户登录”服务编排开发的大致过程:先拖拽1个脚本图元,3个决策图元以及3个赋值图元,再分别配置各个图元属性,然后配置各个图元之间连线类型,最后保存启用。 在“我的应用”中,单击“设备维修管理系统”,进入应用。 在“User”目录中,将鼠标放在“Flow”上,单击界面上出现的“+”,在弹出菜单中选择“服务编排”。 选中“创建一个新的服务编排”,在“标签”和“名称”文本框中输入“login”,并设置类型为“Autolaunched Flow”,单击“添加”。 定义服务编排用到的变量。 单击,展开全局上下文,再单击“变量”后的,设置参数名称为“username”,如图2所示。 图2 新增变量 重复上一步,定义其他变量。 需要定义的变量如表1所示。 表1 服务编排变量说明 变量名称(唯一标识) 数据类型 username(上一步已创建) 文本 password 文本 msg 文本 userId 文本 loginMsg 文本 captcha 文本 profile 文本 单击“公式”后的,在左侧公式弹窗中,设置“名称”为“portalUserLogin”,“表达式”为“PORTALUSER LOG IN({!username})”,单击“保存”。 图3 添加公式变量“portalUserLogin” 参考上一步,创建公式变量“verifyCode”,需要定义的变量如表2所示。 表2 公式变量说明 名称 表达式 verifyCode VERIFYCODEWITHTYPE({!captcha},"login") 拖拽图元到服务编排画布,并配置图元的基本属性。 从图元区分别拖拽脚本(1个)、决策(3个)、赋值(3个)图元到画布中,排列,如图4所示。 图4 拖拽脚本(1个)、决策(3个)、赋值(3个)图元 选中“Script0”图元,在右侧基本信息中,设置“标签”为“查询用户”。 参考5.b,设置其他图元的“标签”属性,具体值如表3所示。 表3 图元基本属性 名称(变量唯一标识,不需要修改) 标签 Script0(上一步已设置) 查询用户 Decision0 判断账号密码 Decision1 判断是否包含验证码 Decision2 校验验证码 Assignment0 账号密码错误 Assignment1 执行登录 Assignment2 验证失败 图5 修改后图元 配置“查询用户”脚本图元。 单击,指定图元对应的脚本名称 (HW__login),并配置脚本的输入输出参数。 单击“全局上下文”,显示变量列表,从“变量”中,拖拽“username”、“password”、“captcha”到“输入参数”下对应的“源”输入框中。 在“输出参数”下,单击5次“新增行”,依次添加下拉选项中的输出参数字段,并从“变量”中拖拽相应的字段到“目标”输入框下,字段与变量对应关系如图6所示。 请直接从全局上下文拖拽“变量”到对应的输入输出参数下,请勿手动输入,手动输入的值系统可能不识别。 图6 拖拽脚本的输入输出参数 配置“判断账号密码”决策图元。 选择“判断账号密码”图元,在右侧单击图标,修改“默认”的“名称”为“loginFail”。 图7 修改“默认”结果名称 单击“新增”,增加一个可编辑的结果,修改结果为“loginSuccess”,在“可视”下单击“新增行”,并拖拽变量中的“msg”到“资源”下,设置“比较符”为“==”,“值”为“"登录成功!"”。 请直接从全局上下文拖拽变量“msg”到“资源”下,请勿手动输入,手动输入的值系统可能不识别。 "登录成功!"需要与“login”脚本中的输出参数一致。 图8 修改可编辑的结果 配置“判断是否包含验证码”决策图元。 选择“判断是否包含验证码”图元,在右侧单击图标,修改“默认”的“名称”为“hasVerifyCode”。 图9 修改“默认”结果名称 单击“新增”,增加一个可编辑的结果,修改结果为“noVerifyCode”,在“可视”下单击“新增行”,并拖拽变量中的“captcha”到“资源”下,设置“比较符”为“==”,“值”为“""”。 图10 修改可编辑的结果 配置“校验验证码”决策图元。 选择“校验验证码”图元,在右侧单击图标,修改“默认”的“名称”为“verifyCodeFail”。 图11 修改“默认”名称 单击“新增”,增加一个可编辑的结果,修改结果为“verifyCodeSuccess”,在右侧选择“公式”,并从全局上下文中,拖拽“verifyCode”到“公式”下。 图12 修改可编辑的结果 配置“账号密码错误”赋值图元。 选择“账号密码错误”图元,在右侧单击图标,单击“新增行”,从全局上下文的“系统变量”中,拖拽“$Flow.ResMsg”到“赋值”下,并设置“操作符”为“=”,拖拽“msg”到“值”;然后再拖拽“系统变量”下的“$Flow.ResCode”到“赋值”的“变量”下,设置“操作符”为“=”,设置“值”为“"1"”。 请直接从全局上下文拖拽变量到“赋值”下的对应位置,请勿手动输入,手动输入的值系统可能不识账。 图13 配置“账号密码错误”图元 配置“执行登录”赋值图元。 选择“执行登录”图元,在右侧单击图标,单击5次“新增行”。 从全局上下文,拖拽“msg”等字段到“赋值”的“变量”下,并设置“操作符”为“=”,然后再拖拽“值”下的各个值,具体字段对应关系,如图14所示。 图14 拖拽“执行登录”赋值的变量及值 请直接从全局上下文拖拽变量到“值”下的对应位置,请勿手动输入,手动输入的值系统可能不识别。 表4 变量与值对应关系 变量 操作符 值 loginMsg = portalUserLogin msg = msg profile = profile username = username userId = userId 配置“验证失败”赋值图元。 选择“验证失败”图元,在右侧单击图标,单击“新增行”,从全局上下文“系统变量”,拖拽“$Flow.ResMsg”、“$Flow.ResCode”到“赋值”下,并设置操作符为“=”,分别设置“值”为“"验证码错误!"”、“"1"”。 表5 赋值 变量 操作符 值 $Flow.ResMsg = "验证码错误!" $Flow.ResCode = "1" 图15 配置“验证失败”赋值图元 拖拽图元连线,并配置连线属性。 在画布上,把鼠标放在起点图元图元上,从“+”拖动鼠标,在起点图元和“查询用户”图元间增加连线;即将当前脚本设置为服务编排的起始节点。 依次在“查询用户”、“判断账号密码”、“判断是否包含验证码”、“执行登录”图元直接拖拽连线。 图16 拖拽连线 单击“判断账号密码”与“判断是否包含验证码”图元之间的连线,再右侧属性单击,在“连线”中修改“连线类型”为“loginSuccess”。 图17 选中连线 图18 修改连线类型 单击“判断是否包含验证码”与“执行登录”图元之间的连线,再右侧属性单击,在“连线”中修改“连线类型”为“noVerifyCode” 从“判断账号密码”图元上拖拽一条连线到“账号密码错误”图元。 从“判断是否包含验证码”图元上拖拽一条连线到“校验验证码”图元。 从“校验验证码”图元上拖拽一条连线到“验证失败”图元。 从“校验验证码”图元上拖拽一条连线到“执行登录”图元,并设置该连线的“连线类型”为“verifyCodeSuccess”。 连线拖拽完成,如图19所示。 图19 拖拽图元连线 定义服务编排的输入、输出参数,并保存服务编排。 鼠标在画布空白处点一下,单击右侧,设置服务编排的输入输出参数,如图20所示。 图20 拖拽服务编排的输入输出参数 单击服务编排页面上方的,保存服务编排。 系统会弹出窗口,显示编译结果。 测试服务编排能否正常执行。 单击服务编排编辑器上方的,执行服务编排。 在“Flow Run”界面中输入测试数据,单击“运行”。其中,“test_cs”、“{XXXXXXXX}”为用户注册脚本中测试数据。 { "username": "test_cs", "password": "{XXXXXXXX}", "captcha": "" } 执行成功,界面上会返回设备对象中的全部信息,样例如下: { "interviewId": "002N000000jjQ95dKbCK", "outputs": { "loginMsg": "null", "msg": "登录成功!", "profile": "cs", "userId": "10gg0XXXXXXXXXXXXX", "username": "test_cs" } } (可选)在服务编排编辑器单击“跟踪”,可以查看到上一步的执行日志,方便定位错误。 测试成功,单击服务编排编辑器上方的,启用发布服务编排。
  • 实现原理 图1 用户登录服务编排大致设想 如图1所示,用户登录服务编排业务逻辑实现过程如下: 通过调用“用户登录”脚本,查询登录账户密码,然后使用“决策”图元进行判断,判断当前登录的账号密码是否正确。 如果判断账户密码错误,直接执行“账户密码错误”,判断账户密码正确,则使用“决策”图元,继续判断是否有验证码。 如果判断当前登录没有验证码,则直接执行登录,判断当前有验证码,则继续判断验证码是否正确。 如果判断验证码正确,则执行登录操作,判断验证码错误,则执行验证失败。
  • 操作步骤 在“我的应用”中,单击“设备维修管理系统”,进入应用。 在“User”目录中,将鼠标放在“Script”上,单击界面上出现的“+”,在弹出菜单中选择“脚本”。 在弹窗中,选中“创建一个新脚本”,在“名称”文本框中输入“registerPortalUser”,单击“添加”。 在代码编辑器中,插入如下脚本代码。 import * as buffer from "buffer"; import * as crypto from "crypto"; import * as db from "db"; import * as context from 'context'; import * as http from 'http'; import * as permission from 'permission'; //定义入参结构,包括注册账号的用户名、密码和角色,为必填字段 @action.object({ type: "param" }) export class ActionInput { @action.param({ type: 'String', required: true, label: 'string' }) username: string; @action.param({ type: 'String', required: true, label: 'string' }) password: string; @action.param({ type: 'String', required: true, label: 'string' }) role: string; } //定义出参结构,出参包含1个参数,portaluser的记录id @action.object({ type: "param" }) export class ActionOutput { @action.param({ type: 'String' }) msg: string; } //使用数据对象PortalUser @useObject(['PortalUser']) @action.object({ type: "method" }) export class RegisterPortalUser { //定义接口类,接口的入参为ActionInput,出参为ActionOutput @action.method({ input: 'ActionInput', output: 'ActionOutput' }) public registerPortalUser(input: ActionInput): ActionOutput { let out = new ActionOutput(); //新建出参ActionOutput类型的实例,作pu为返回值 let error = new Error(); //新建错误类型的实例,用于在发生错误时保存错误信息 try { let s = db.object('PortalUser'); let saltedPassword = salt(input.password); let userMsg = { "usrName": input.username, "name": input.username, "userPassword": saltedPassword['saltedPassword'], "passwordSalt": saltedPassword['salt'], "userType": input.role }; let userId = s.insert(userMsg); if (userId) { out.msg = "注册成功!"; } else { error.name = "USERERROR"; error.message = "注册失败!"; throw error; } } catch (error) { if (error.name == "405230618") { error.message = "该用户名已注册!" } console.error(error.name, error.message); context.setError(error.name, error.message); } return out; } } function _salt(password: string, saltBuf: buffer.Buffer, encoding: buffer.Encoding = buffer.Encoding.Base64): string { const passwordBuf = buffer.from(password) const crypt = crypto.pbkdf2(passwordBuf, saltBuf, 1000, 32, crypto.Hashs.SHA1) return crypt.toString(encoding) } function salt(password: string, encoding: buffer.Encoding = buffer.Encoding.Base64): object { const saltBuf = crypto.randomBytes(6) const saltedPassword = _salt(password, saltBuf, encoding) return { salt: saltBuf.toString(encoding), saltedPassword: saltedPassword } } 单击编辑器上方的,保存脚本。 测试脚本能否正常执行。 单击编辑器上方的,执行脚本。 在界面底部输入测试数据,单击测试窗口右上角执行图标。 { "username": "test_cs", "password": "***", "role": "cs" } 执行成功,会在“输出”页签返回查询结果。 { "msg": "注册成功!" } 测试成功,单击编辑器上方的,启用发布脚本。
  • 操作步骤 在“我的应用”中,单击“设备维修管理系统”,进入应用。 在“User”目录中,将鼠标放在“Script”上,单击界面上出现的“+”,在弹出菜单中选择“脚本”。 在弹窗中,选中“创建一个新脚本”,在“名称”文本框中输入“registerPortalUser”,单击“添加”。 在代码编辑器中,插入如下脚本代码。 import * as buffer from "buffer"; import * as crypto from "crypto"; import * as db from "db"; import * as context from 'context'; import * as http from 'http'; import * as permission from 'permission'; //定义入参结构,包括注册账号的用户名、密码和角色,为必填字段 @action.object({ type: "param" }) export class ActionInput { @action.param({ type: 'String', required: true, label: 'string' }) username: string; @action.param({ type: 'String', required: true, label: 'string' }) password: string; @action.param({ type: 'String', required: true, label: 'string' }) role: string; } //定义出参结构,出参包含1个参数,portaluser的记录id @action.object({ type: "param" }) export class ActionOutput { @action.param({ type: 'String' }) msg: string; } //使用数据对象PortalUser @useObject(['PortalUser']) @action.object({ type: "method" }) export class RegisterPortalUser { //定义接口类,接口的入参为ActionInput,出参为ActionOutput @action.method({ input: 'ActionInput', output: 'ActionOutput' }) public registerPortalUser(input: ActionInput): ActionOutput { let out = new ActionOutput(); //新建出参ActionOutput类型的实例,作pu为返回值 let error = new Error(); //新建错误类型的实例,用于在发生错误时保存错误信息 try { let s = db.object('PortalUser'); let saltedPassword = salt(input.password); let userMsg = { "usrName": input.username, "name": input.username, "userPassword": saltedPassword['saltedPassword'], "passwordSalt": saltedPassword['salt'], "userType": input.role }; let userId = s.insert(userMsg); if (userId) { out.msg = "注册成功!"; } else { error.name = "USERERROR"; error.message = "注册失败!"; throw error; } } catch (error) { if (error.name == "405230618") { error.message = "该用户名已注册!" } console.error(error.name, error.message); context.setError(error.name, error.message); } return out; } } function _salt(password: string, saltBuf: buffer.Buffer, encoding: buffer.Encoding = buffer.Encoding.Base64): string { const passwordBuf = buffer.from(password) const crypt = crypto.pbkdf2(passwordBuf, saltBuf, 1000, 32, crypto.Hashs.SHA1) return crypt.toString(encoding) } function salt(password: string, encoding: buffer.Encoding = buffer.Encoding.Base64): object { const saltBuf = crypto.randomBytes(6) const saltedPassword = _salt(password, saltBuf, encoding) return { salt: saltBuf.toString(encoding), saltedPassword: saltedPassword } } 单击编辑器上方的,保存脚本。 测试脚本能否正常执行。 单击编辑器上方的,执行脚本。 在界面底部输入测试数据,单击测试窗口右上角执行图标。 { "username": "test_cs", "password": "***", "role": "cs" } 执行成功,会在“输出”页签返回查询结果。 { "msg": "注册成功!" } 测试成功,单击编辑器上方的,启用发布脚本。
  • 创建公共接口 在设计视图下,单击“服务”,进入公共接口创建页面。 图1 服务入口 单击“新建”,如图2所示。 图2 公共接口创建 创建“用户登录”、“用户注册”脚本对应的公共接口,详细接口信息如表1所示。 如果在“资源”下拉框中,未找到需要关联的脚本或服务编排,请检查相关脚本和服务编排是否已启用,加粗斜体内容以实际命名空间前缀为准。 表1 公共接口 设置操作 版本 URL 方法 类型 资源 login 1.0.0 /login POST 服务编排 HW__login registerPortalUser 1.0.0 /registerPortalUser POST 脚本 HW__registerPortalUser 父主题: 开发业务逻辑