
# 业务用户登录页后端逻辑开发实施步骤
业务用户在后台登录时，是使用自定义的服务编排，来调用"账号密码校验"脚本，查询登录账号密码，判断当前登录的账号密码是否正确来实现"业务用户"后台登录功能的。"业务用户登录"服务编排开发的大致过程为：先拖拽1个脚本图元，3个决策图元以及3个赋值图元，再分别配置各个图元属性，然后配置各个图元之间连线类型，最后保存启用。
下面以"A"应用为例，介绍如何在后台实现业务用户登录。
#### 步骤一：创建密码校验登录脚本
业务用户登录前，需要先创建一个账号密码校验脚本。
1. 在华为云Astro轻应用服务控制台的主页中，单击"进入首页"，进入华为云Astro轻应用应用开发页面。
2. 在"主页 \> 全部应用"中，单击"A"应用后的"编辑"，进入应用设计器。
3. 在左侧导航栏中，选择"逻辑"，单击脚本后的"+"。
4. 选中"创建一个新脚本"，"名称"设置为"login"，单击"添加"。 
   图1新增脚本   
   ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002161496341.png "点击放大")
   
   
5. 在代码编辑器中，插入如下脚本代码。 
   ```
   import * as buffer from"buffer";
   import * as crypto from"crypto";
   import * as db from"db";
   //定义入参结构，账号的用户名、密码为必需字段。如果根据业务需要，需校验其他字段（例如验证码），则根据账号密码字段的格式进行新增即可。
   @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'})
       captcha:string;     //验证码，本脚本只是为了校验账号密码，因此用不到验证码，验证码也不是必需字段。在实现业务用户后台登录的Flow中，Flow调用此脚本，需要判断验证码，所以在此脚本中添加了验证码字段。
   }
   //定义出参结构，结构中的字段可以根据业务需要按下方样例结构进行添加或减少。
   @action.object({type:"param"})
   export class ActionOutput{
       @action.param({type:'String'})
       msg:string;//登录信息    
       @action.param({type:'String'})
       username:string;//用户名    
       @action.param({type:'String'})
       userId:string;//用户ID
       @action.param({type:'String'})
       captcha:string;//验证码
   }
   //使用数据对象PortalUser
   @useObject(['PortalUser'])
   @action.object({type:"method"})
   export class Login{
   //定义接口类，接口的入参为ActionInput，出参为ActionOutput    
       @action.method({ input:'ActionInput', output:'ActionOutput'})
       public login(input:ActionInput):ActionOutput{
           let out =new ActionOutput();
           //新建出参ActionOutput类型的实例，作为返回值        
           let error =new Error();
           //新建错误类型的实例，用于在发生错误时保存错误信息        
           try{
               out.captcha = input.captcha;
               let s = db.object('PortalUser');
               let condition ={
               "conjunction":"AND",
               "conditions":[{
                   "field":"usrName",
                   "operator":"eq",
                   "value": input.username
                   }]
               };
               let user = s.queryByCondition(condition);
               if(user && user.length ==1){
                   if(validate(user[0].passwordSalt, user[0].userPassword, input.password)){
                       out.msg ="登录成功！";
                       out.username = user[0].usrName;
                       out.userId = user[0].id;
                   }else{
                       out.msg ="账号或者密码错误！";
                   }
               }else{
                   out.msg ="账号或者密码错误！";
               }
           }catch(error){
               console.error(error.name, error.message);
               out.msg = 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 validate(salt:string, userSaltedPassword:string, password:string, encoding: buffer.Encoding= buffer.Encoding.Base64):boolean{
       const saltBuf = buffer.from(salt, encoding);
       const saltedPassword = _salt(password, saltBuf, encoding);
       return saltedPassword === userSaltedPassword
   }
   ```
   
   
6. 单击编辑器上方的![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001971723433.png)，保存脚本。
7. 测试脚本能否正常执行。 
   1. 单击编辑器上方的![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001944764294.png)，执行脚本。
   
   2. 在界面底部的输入参数中，输入如下测试数据，单击![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001971843161.png)。
      其中，"test_cs"、"*{XXXXXXXX}*"为注册的业务用户账号和密码，"captcha"验证码非必填项为空。
      **在业务配置中心创建的业务用户和使用脚本创建的业务用户不能通用，故此处设置的业务用户（如test_cs）不能为在业务配置中心创建的业务用户。业务配置中心创建的业务用户，只能在默认登录页中使用。**
      ```
      {
          "username": "test_cs",
          "password": "{XXXXXXXX}",
          "captcha": ""
      }
      ```
      执行成功后，在"输出参数"中可参看结果。
      ```
      {{
          "captcha": "",
          "msg": "登录成功！",
          "userId": "10*******A",
          "username": "test_cs"
      }
      ```
      
   
   
   
   
8. 测试成功后，单击编辑器上方的![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001971723437.png)，启用该脚本。
 
 #### 步骤二：通过服务编排开发登录页后端逻辑
1. 在"A"应用的设计器中，单击左侧导航栏的"逻辑"，单击编排后的![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001949500317.png)，新建一个Flow目录。
   
   图2创建目录   
   ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001992552765.png "点击放大")
   
   
2. 将鼠标放在"Flow"上，单击界面上出现的"+"，进入添加服务编排页面。
3. 选中"创建一个新的服务编排"，"标签"和"名称"设置为"login"，类型设置为"Autolaunched Flow"，单击"添加"。 
   图3创建服务编排   
   ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002126218004.png "点击放大")
   
   
4. 定义服务编排用到的变量。 
   1. 单击![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001948461221.png)，展开全局上下文，再单击"变量"后的![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001919142230.png)，设置参数名称为"username"。
      图4新增变量   
      ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001918982298.png) 
   
   2. 重复上一步，定义[表1]中其他变量。
       表1服务编排变量说明 
      | 名称（变量名称，唯一标识） | 数据类型 |
      |:---|:---|
      | username      | 文本   |
      | password      | 文本   |
      | captcha       | 文本   |
      | msg           | 文本   |
      | userId        | 文本   |
      | loginMsg      | 文本   |
         
      
   
   3. 单击"公式"后的![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001948461233.png)，在左侧公式弹窗中，设置"名称"为"portalUserLogin"，"表达式"为"PORTALUSERLOGIN({!username})"，单击"保存"。
      图5添加公式变量"portalUserLogin"   
      ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002126381996.png "点击放大") 
   
   4. 参考上一步，创建[表2]中公式变量"verifyCode"。
       表2公式变量说明 
      | 名称              | 表达式                                    |
      |:---|:---|
      | portalUserLogin | PORTALUSERLOGIN({!username})           |
      | verifyCode      | VERIFYCODEWITHTYPE({!captcha},"login") |
         
      
   
   
   
   
5. 拖拽图元到服务编排画布，并配置图元的基本属性。 
   1. 从图元区分别拖拽脚本（1个）、决策（3个）、赋值（3个）图元到画布中，图元排列如下图所示。
      图6图元排列   
      ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002161507157.png "点击放大") 
   
   2. 选中"Script0"图元，在右侧基本信息中，设置"标签"为"查询用户"。
   
   3. 参考上一步，设置其他图元的"标签"属性，具体值如下表所示。
      表3设置其他图元标签属性 
      | 名称（变量唯一标识，不需要修改） | 标签        |
      |:---|:---|
      | Decision0        | 判断账号密码    |
      | Decision1        | 判断是否包含验证码 |
      | Decision2        | 校验验证码     |
      | Assignment0      | 账号密码错误    |
      | Assignment1      | 执行登录      |
      | Assignment2      | 验证失败      |
         
      图7修改后图元   
      ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002161507993.png "点击放大") 
   
   
   
   
6. 配置"查询用户"脚本图元。 
   1. 单击![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001919142250.png)，指定图元对应的脚本名称 （*命名空间* __login），并配置脚本的输入输出参数。
      图8指定脚本   
      ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001992674997.png "点击放大") 
   
   2. 单击"全局上下文"，显示变量列表，从"变量"中，拖拽"username"、"password"和"captcha"到"输入参数"下对应的"源"输入框中，在"输出参数"下，单击4次"新增行"，依次添加下拉选项中的输出参数字段，并从"变量"中拖拽相应的字段到"目标"输入框下，字段与变量对应关系如下图所示。
      - 脚本图元中，输入参数、输出个数和指定脚本中需要的输入参数字段数是一致的。如果自定义脚本的输入参数有额外字段，额外的字段也需要同样操作。
      
      - 请直接从全局上下文拖拽"变量"到对应的输入输出参数下，如果手动输入请确认输入参数与全局上下文中变量的值一致。
      
      
      图9拖拽脚本的输入输出参数   
      ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002126233020.png "点击放大") 
   
   
   
   
7. 配置"判断账号密码"决策图元。 
   1. 选择"判断账号密码"图元，在右侧单击![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001919142258.png)图标，修改"默认"的"名称"为"CheckFail"。
      图10修改"默认"结果名称   
      ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001918982322.png "点击放大") 
   
   2. 单击"新增"，增加一个可编辑的结果，修改结果为"CheckSuccess"，在"可视"下单击"新增行"，并拖拽变量中的"msg"到"资源"下，设置"比较符"为"=="，"值"为""登录成功！""。
      图11修改可编辑的结果   
      ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002162175069.png "点击放大")
      - 请直接从全局上下文拖拽变量"msg"到"资源"下，如果手动输入请确认输入参数与全局上下文中变量的值一致。
      
      - "登录成功！"需要与"login"登录脚本中的输出参数一致。
       
   
   
   
   
8. 配置"判断是否包含验证码"决策图元。 
   1. 选择"判断是否包含验证码"图元，在右侧单击![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001919142266.png "点击放大")图标，修改"默认"的"名称"为"hasVerifyCode"。
      图12修改默认结果名称   
      ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002126396584.png "点击放大") 
   
   2. 单击"新增"，增加一个可编辑的结果，修改结果为"noVerifyCode"，在"可视"下单击"新增行"，并拖拽变量中的"captcha"到"资源"下，设置"比较符"为"=="，"值"为""""。
      图13修改可编辑的结果   
      ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002126399568.png "点击放大") 
   
   
   
   
9. 配置"校验验证码"决策图元。 
   1. 选择"校验验证码"图元，在右侧单击![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001919142270.png "点击放大")图标，修改"默认"的"名称"为"verifyCodeFail"。
      图14修改"默认"名称   
      ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002161680137.png "点击放大") 
   
   2. 单击"新增"，增加一个可编辑的结果，修改结果为"verifyCodeSuccess"，在右侧选择"公式"，并从全局上下文中，拖拽"verifyCode"到"公式"下。
      图15修改可编辑的结果   
      ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002162055713.png "点击放大") 
   
   
   
   
10. 配置"账号密码错误"赋值图元。 
    图16配置"账号密码错误"图元   
    ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002126975134.png "点击放大")
    1. 选择"账号密码错误"图元，在右侧单击![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001919142274.png)图标，单击"新增行"。
    
    2. 从全局上下文的"系统变量"中，拖拽"$Flow.ResMsg"到"赋值"下，并设置"操作符"为"="，拖拽"msg"到"值"。
    
    3. 单击"新增行"，拖拽"系统变量"下的"$Flow.ResCode"到"赋值"的"变量"下，设置"操作符"为"="，设置"值"为""1""。
    
    
    
    
11. 配置"执行登录"赋值图元。 
    图17拖拽"执行登录"赋值的变量及值   
    ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002162174345.png "点击放大")
    1. 选择"执行登录"图元，在右侧单击![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001948461273.png)图标，单击4次"新增行"。
    
    2. 从全局上下文，拖拽"msg"等字段到"赋值"的"变量"下，并设置"操作符"为"="，然后再拖拽"值"下的各个值，具体字段对应关系，如下图所示。
       表4变量与值对应关系 
       | 变量       | 操作符 | 值                  |
       |:---|:---|:---|
       | loginMsg | =   | {!portalUserLogin} |
       | msg      | =   | {!msg}             |
       | username | =   | {!username}        |
       | userId   | =   | {!userId}          |
          
       
    
    
    
    
12. 配置"验证失败"赋值图元。 
    图18配置"验证失败"赋值图元   
    ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002162055977.png "点击放大")
    1. 选择"验证失败"图元，在右侧单击![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001918982346.png)图标，单击"新增行"。
    
    2. 从全局上下文"系统变量"，拖拽"$Flow.ResMsg"、"$Flow.ResCode"到"赋值"下，并设置操作符为"="，分别设置"值"为""账号或者密码错误！""、""1""。
    
    
    表5赋值 
    | 变量            | 操作符 | 值           |
    |:---|:---|:---|
    | $Flow.ResMsg  | =   | "账号或者密码错误！" |
    | $Flow.ResCode | =   | "1"         |
       
    
    
13. 拖拽图元连线，并配置连线属性。 
    1. 在画布上，把鼠标放在起点图元上，从"+"拖动鼠标，在起点图元和"查询用户"图元间增加连线；即将当前脚本设置为服务编排的起始节点。
    
    2. 依次在"查询用户"、"判断账号密码"、"判断是否包含验证码"、"执行登录"图元直接拖拽连线。
       图19拖拽连线   
       ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001918982350.png "点击放大") 
    
    3. 单击"判断账号密码"与"判断是否包含验证码"图元之间的连线，在右侧属性单击![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001948461281.png)，在"连线"中修改"连线类型"为"CheckSuccess"。
       图20选中连线   
       ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002162056113.png "点击放大") 
    
    4. 单击"判断是否包含验证码"与"执行登录"图元之间的连线，在右侧属性单击![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001948461285.png)，在"连线"中修改"连线类型"为"noVerifyCode"。
    
    5. 从"判断账号密码"图元上，拖拽一条连线到"账号密码错误"图元。
    
    6. 从"判断是否包含验证码"图元上，拖拽一条连线到"校验验证码"图元。
    
    7. 从"校验验证码"图元上，拖拽一条连线到"验证失败"图元。
    
    8. 从"校验验证码"图元上，拖拽一条连线到"执行登录"图元，并设置该连线的"连线类型"为"verifyCodeSuccess"。
    
    
    连线拖拽完成，如下图所示。
    图21拖拽图元连线   
    ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001919142294.png "点击放大")
    
    
14. 定义服务编排的输入、输出参数，并保存服务编排。 
    1. 鼠标在画布空白处点一下，单击右侧![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001918982358.png)，设置服务编排的输入输出参数，如下图所示。
       图22拖拽服务编排的输入输出参数   
       ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002126974770.png "点击放大")
       - 服务编排的输入参数是用来执行服务编排时输入的参数，同时也是执行账号密码校验脚本时的输入参数。所以当账号密码校验脚本时，如果有额外的输入参数字段，服务编排的输入参数也需要同步增加。
       
       - 服务编排的输出参数是执行账号密码校验脚本时返回的参数，所以当账号密码校验脚本时，如果有额外的输出参数字段，服务编排的输出参数也需要同步增加。
        
    
    2. 单击服务编排页面上方的![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001919142298.png)，保存服务编排。
    
    
    
    
15. 测试服务编排能否正常执行。 
    1. 单击服务编排页面上方的![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001918982362.png)，进入服务编排测试页面。
       图23服务编排测试页面   
       ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001948461293.png) 
    
    2. 在"Flow Run"界面中，输入测试数据，单击"运行"。
       其中，"test_cs"、"*\*\*\** "为业务用户的账号和密码。
       ```
       {
        "username": "test_cs",
        "password": "***",
        "captcha": ""
        }
       ```
       执行成功后，界面上会返回设备对象中的全部信息，示例如下：
       图24返回值示例   
       ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001919142302.png)
       返回值提示"登录成功"，完成业务用户的登录。业务用户登录成功后，返回华为云Astro轻应用，刷新页面后在页面右上角可以看到当前登录的用户已变成在服务编排中输入的业务用户。
       
    
    
    
    
16. 测试成功后，单击编辑器上方的![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000001918982366.png)，启用并发布服务编排。
17. 测试成功，使用平台开发者用户重新登录，单击服务编排编辑器上方的![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002361875502.png)，启用并发布服务编排。
    
    ![](https://support.huaweicloud.com/bestpractice-astrozero/public_sys-resources/note_3.0-zh-cn.png)
    测试成功后，此时页面的登录用户已经变成了在服务编排中输入的业务用户，直接单击服务编排编辑器上方的![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002361715598.png)，会报无权限执行，因此需要切换为平台开发者用户重新登录后再启用该编排。
    
    
 
#### 步骤三：新建开放接口
开放接口是用户将在应用中开发的脚本、服务编排等包装成自定义REST接口的形式，供其他系统进行调用。本示例将开发的服务编排包装发布REST接口，供[业务用户登录页前台开发实施步骤](https://support.huaweicloud.com/bestpractice-astrozero/astrozero_bestpractice_0050.html)中操作调用。
1. 在"A"应用的设计器中，单击左侧导航栏的"集成"。
2. 单击开放接口后的"+"，进入新建开放接口页面。
3. 设置接口参数，单击"保存"。 
   图25新建开放接口   
   ![](https://support.huaweicloud.com/bestpractice-astrozero/zh-cn_image_0000002162175045.png "点击放大")
   表6开放接口参数说明 
   | 参数   | 说明                                                                                        | 示例                                                                                                         |
   |:---|:---|:---|
   | 标签   | 新建API接口的标签，长度不能超过64个字符。                                                                   | login                                                                                                      |
   | 操作名称 | 新建API接口的操作名称，必须以英文字母开头，由英文字母，数字和单下划线组成，不能以单下划线结尾，且长度不能超过40个字符。                            | login                                                                                                      |
   | 版本   | API接口的版本，格式为"x.y.z"。                                                                      | 1.3.3                                                                                                      |
   | URL  | API接口路径， 固定以 /service/*{命名空间}__{应用名}* /*{版本}* 开头， 后面接API的具体路径。此处设置的内容是新建开放接口提供给外部访问的URL。  | /service/*命名空间* __A/*版本*/Flow_login                                                                        |
   | 类型   | 选择资源类型，只有服务编排类型的接口能够在服务编排中被调用，其他类型接口只能通过API的形式进行调用。                                       | 服务编排                                                                                                       |
   | 资源   | 根据类型选择需要绑定的资源。                                                                            | 选择[步骤二：通过服务编排开发登录页后端逻辑]中创建的服务编排，请确保服务编排已启用，否则此处选择不到。 |
   | 方法   | API接口的HTTP方法。 本示例选择"POST"，即请求服务器新增资源或执行特殊操作。 | POST                                                                                                       |
      
   
   
 
