
# 同步第三方认证协议用户到华为云Astro轻应用
华为云Astro轻应用支持通过自定义认证，配置华为云Astro轻应用对接第三方应用认证的必要信息，将第三方应用中的业务用户同步到华为云Astro轻应用的业务配置中心。在业务配置中心根据业务需求赋予业务用户相应的权限，配置后业务用户即可对应用进行相关的操作。
#### 新建自定义认证
1. 在华为云Astro轻应用服务控制台，单击"进入首页"，进入应用开发页面。
2. 在页面左上方单击![](https://support.huaweicloud.com/usermanual-astrozero/zh-cn_image_0000001917373754.png)，选择"环境管理 \> 环境配置"，进入环境配置。
3. 在左侧导航栏中，选择"集成连接 \> 统一身份认证"，单击"自定义认证 \> 新建"。
4. 在"基本配置"中，输入标签和名称后，单击"下一步"。
5. 在"认证源配置"中，设置认证源信息，单击"下一步"。
   
   图1"Oauth2"认证配置   
   ![](https://support.huaweicloud.com/usermanual-astrozero/zh-cn_image_0000001894298792.png "点击放大")
   表1"Oauth2"协议认证配置字段说明 
   | 参数               | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
   |:---|:---|
   | 认证协议             | 根据对端认证服务器提供的认证协议进行选择，此处选择"Oauth2"。                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
   | 认证地址             | 设置认证登录地址，请从第三方获取。                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
   | 获取access_token地址 | 获取access_token的请求地址，请从第三方获取。                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
   | 获取用户信息地址         | 获取用户信息的请求地址，请从第三方获取。                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
   | access_token参数位置 | 获取用户信息时，传入access_token的参数位置。                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
   | 请求方法             | 调用获取用户信息接口的请求方法。                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
   | 登出地址             | 华为云Astro轻应用登出之后，跳到服务端的登出地址，使服务端登出，建议配置登出地址。支持在登出地址中添加变量"{redirect}"，登出时替换为当前配置的页面地址。 示例：https://*host*/api/v1/logout?redirect_url={redirect}                                                                                                                                                                                                                                                                            |
   | 是否登录时自动创建用户      | 用户首次登录时，如果系统中不存在此用户，是否自动创建用户。                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
   | 用户权限             | 当使用第三方用户登录时，如果用户不存在，且开启了自动创建用户，此权限将作为创建用户的默认权限。                                                                                                                                                                                                                                                                                                                                                                                                                                          |
   | 是否校验state        | 是否需要检验state参数。建议开启校验state，以防止CSRF攻击。 华为云Astro轻应用在响应请求后，将重定向到第三方服务器，此时第三方服务器根据该配置决定是否校验state参数一致性（即cookie或session里的state）。如果开启校验后，state不一致，则华为云Astro轻应用拒绝此请求，且不再发起换取access_token的请求。如果一致，则流程正常运行。                                                                                                                                                                                                                       |
   | 属性映射             | 配置华为云Astro轻应用和第三方的属性映射关系，即映射华为云Astro轻应用和第三方登录接口返回的用户属性相同的字段。 请到对端第三方获取用户信息，返回的用户信息如下： ``` { "id" : "20201029190841785-CB37-8BD36B...", // 用户ID "name" : "test", // 名称 "userName" : "test", // 用户登录名 "mobile" : "1XXXX456789", // 电话号码 "email" : "123@example.com" // 邮箱 "local" : "zh_CN" // 用户语言 } ``` 获取上述信息后，参照[图1]配置第三方字段和华为云Astro轻应用对应字段的属性映射关系。 |
      
   图2"CAS"认证配置   
   ![](https://support.huaweicloud.com/usermanual-astrozero/zh-cn_image_0000001894298788.png "点击放大")
   表2"CAS"协议认证配置字段说明 
   | 参数          | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
   |:---|:---|
   | 认证协议        | 根据对端认证服务器提供的认证协议进行选择，此处选择"CAS"。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
   | 认证地址        | 认证登录地址，请从第三方获取。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
   | 验证票据地址      | 验证票据并获取用户属性信息的地址，请从第三方获取。 "认证协议"配置为"CAS"时，才需配置此参数。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
   | 登出地址        | 华为云Astro轻应用登出之后，跳到服务端的登出地址，使服务端登出，建议配置登出地址。支持在登出地址中添加变量"{redirect}"，登出时替换为当前配置的页面地址。 示例：https://*host*/api/v1/logout?redirect_url={redirect}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
   | 是否登录时自动创建用户 | 用户首次登录时，如果系统中不存在此用户，是否自动创建用户。 - 是：自动创建用户并登录。  - 否：直接登录失败。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
   | 用户权限        | 当使用第三方用户登录时，如果用户不存在，且开启了自动创建用户，此权限将作为创建用户的默认权限。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
   | 属性映射        | 配置华为云Astro轻应用和第三方的属性映射关系，即映射华为云Astro轻应用和第三方登录接口返回的用户属性相同的字段。 请到对端第三方获取用户信息，返回的用户信息如下： ``` <cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas"> <cas:authenticationSuccess> <cas:user>Lily</cas:user> // 用户登录名称 <cas:attributes> <cas:authenticationDate>2020-02-11T09:28:14.987Z</cas:authenticationDate> <cas:longTermAuthenticationRequestTokenUsed>false</cas:longTermAuthenticationRequestTokenUsed> <cas:isFromNewLogin>true</cas:isFromNewLogin> <cas:date>2020-02-03T16:00:00.000Z</cas:date> <cas:birthday>2020-02-04T16:00:00.000Z</cas:birthday> <cas:createAt>2020-01-10T09:01:04.000Z</cas:createAt> <cas:disabledAt>null</cas:disabledAt> <cas:disabled>false</cas:disabled> <cas:email>email@example.com</cas:email> // 邮箱 <cas:local>zh_CN</cas:local> // 用户语言 <cas:token>XXXXXXXXXXXXXXXXX</cas:token> // 第三方系统用户token </cas:attributes> </cas:authenticationSuccess> </cas:serviceResponse> ``` 获取上述信息后，参照[图2]配置第三方字段和华为云Astro轻应用对应字段的属性映射关系。 其中，属性"email"和"phone"可以映射为空，当对端没有对应的"name"和"extIdentityID"字段返回时，可以都配置成"userName"属性对应的字段，"userName"属性对应的字段是必填的。 |
      
   图3"SAML2"认证配置   
   ![](https://support.huaweicloud.com/usermanual-astrozero/zh-cn_image_0000001894138904.png "点击放大")
   表3"SAML2"协议认证配置字段说明 
   | 参数             | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
   |:---|:---|
   | 认证协议           | 根据对端认证服务器提供的认证协议进行选择，此处选择"SAML2"。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
   | 登出地址           | 华为云Astro轻应用登出之后，跳到服务端的登出地址，使服务端登出，建议配置登出地址。支持在登出地址中添加变量"{redirect}"，登出时替换为当前配置的页面地址。 示例：https://*host*/api/v1/logout?redirect_url={redirect}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
   | 是否登录时自动创建用户    | 用户首次登录时，如果系统中不存在此用户，是否自动创建用户。 - 是：自动创建用户并登录。  - 否：直接登录失败。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
   | 用户权限           | 当使用第三方用户登录时，如果用户不存在，且开启了自动创建用户，此权限将作为创建用户的默认权限。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
   | 是否校验state      | 建议开启校验state，以防止CSRF攻击。 华为云Astro轻应用在响应请求后，将重定向到第三方服务器，此时第三方服务器根据该配置决定是否校验state参数一致性（即cookie或session里的state）。如果开启校验后，state不一致，则华为云Astro轻应用拒绝此请求，且不再发起换取access_token的请求。如果一致，则流程正常运行。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
   | 对请求签名          | 是否对发送的SAML请求进行数字签名，以确保请求的完整性和来源的可信度。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
   | 客户端证书          | SAML客户端签名证书公钥。 自签名证书公钥如"saml.crt"获取方法如下，该方法创建的证书通常只适用于测试场景。 1. 在Linux机器上执行如下命令，生成密钥文件"saml.key"。 ``` openssl genrsa -out saml.key 2048 ``` 命令执行后将在当前目录生成一个"saml.key"的私钥文件。生成的密钥格式必须为： ``` -----BEGIN PRIVATE KEY----- …………………………………………….. -----END PRIVATE KEY----- ```   2. 用上一步的密钥文件去签发，生成文件"saml.csr"。 ``` openssl req -new -key saml.key -out saml.csr ```   3. 根据提示依次输入国家、地区、组织、邮箱及common name（用户名或域名，如果为https申请，该参数值必须和域名相同，否则会引发浏览器警报），按回车键确认。  4. 执行如下命令，使用之前生成的文件去签发生成自己的证书文件"saml.crt"。 ``` openssl x509 -req -days 365 -in saml.csr -signkey saml.key -out saml.crt ``` 生成的证书格式必须为： ``` -----BEGIN CERTIFICATE----- …………………………………………………………… -----END CERTIFICATE----- ```    |
   | 客户端证书私钥        | SAML签名证书私钥。 自签名证书私钥为生成客户端证书中产生的"saml.key"文件，该方法创建的证书通常只适用于测试场景。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
   | Idp Metadata文件 | SAML服务端的元数据文件，需要到SAML身份提供商（Identity Provider，简称IdP）获取。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
   | 属性映射           | 配置华为云Astro轻应用和第三方的属性映射关系，即映射华为云Astro轻应用和第三方登录接口返回的用户属性相同的字段。 其中，属性"email"和"phone"可以映射为空，当对端没有对应的"name"和"extIdentityID"字段返回时，可以都配置成"userName"属性对应的字段，"userName"属性对应的字段是必填的。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
      
   
   
6. 在"身份源配置"中，配置对端鉴权ID、对端鉴权密钥和同步脚本，单击"保存"。 
   当认证协议选择"CAS"后，只需要配置同步脚本。
   图4身份源配置   
   ![](https://support.huaweicloud.com/usermanual-astrozero/zh-cn_image_0000001894138888.png "点击放大")
   同步脚本用于同步第三方机构组织、用户到华为云Astro轻应用。脚本示例如下：
   ```
   // Here's your code./*
   import * as http from 'http';
   import * as db from 'db';
   import * as iconv from 'iconv';
   import { Encoding } from 'buffer';
   export class Output {
       @action.param({ type: "Any" })
       result: any;
   }
   export class StructRole {
       @action.param({ type: "String", description: "组织name，可以对应第三方组织code", isCollection: false })
       name: string;
       @action.param({ type: "String", description: "组织名称，可以对应第三方组织名称", isCollection: false })
       label: string;
       @action.param({ type: "String", description: "上级组织，对应华为云Astro轻应用组织ID", isCollection: false })
       reportTo: string;
   }
   export class StructUser {
       @action.param({ type: "String", description: "用户名称", isCollection: false })
       name: string;
       @action.param({ type: "String", description: "用户账号， 账号内唯一", isCollection: false })
       usrName: string;
       @action.param({ type: "String", description: "第三方系统用户ID, 第三方系统内唯一", isCollection: false })
       extIdentityID: string
       @action.param({ type: "String", description: "所属组织，对应华为云Astro轻应用内组织ID", isCollection: false })
       roleId: string
       @action.param({ type: "String", description: "创建的业务用户权限， profileId", isCollection: false })
       profile: string
       @action.param({ type: "String", description: "创建的业务用户类型，固定为custom", isCollection: false })
       userType: string
   }
   @useObject(['PortalUser'])
   export class SyncContact {
       @action.method({ input: "Input", output: "Output", description: "开发测试时运行此方法" })
       run(): Output {
           //return this.SyncUser();
           return this.SyncRole(); //调试同步组织机构取消注释此行
       }
       // SyncUser为同步用户的方法，方法名不允许修改
       SyncUser(): Output {
           let output = new Output();
           let token = this.getToken();
           if (!token) {
               output.result = "同步用户失败";
               return output;
           }
           let users = this.queryUsers(token);
           for (let u of users) {
               let portaluser: StructUser = {
                   name: u.user_name,
                   usrName: u.user_name,
                   extIdentityID: u.user_id,
                   profile: "000T0000000000000003", // 设置为Portal User Profile的ID
                   roleId: "",
                   userType: "custom"
               }
               let role = this.queryRoleByName("oneaccess" + u.org_id);
               if (role) {
                   portaluser.roleId = role.id;
               }
               this.addUser(portaluser);
           }
           output.result = "同步用户成功";
           return output;
       }
       // SyncRole为同步组织机构的方法，方法名不允许修改
       SyncRole(): Output {
           let output = new Output();
           let token = this.getToken();
           if (!token) {
               output.result = "同步组织机构失败";
               return output;
           }
           let orgs = this.queryOrgs(token, "");
           for (let org of orgs) {
               this.syncOrg(org, token);
           }
           output.result = "同步组织机构成功";
           return output;
       }
       private addUser(portaluser: StructUser): String {
           // 校验记录是否已经存在
           let option = {};
           let condition = {
               "conjunction": "AND",
               "conditions": [{
                   "field": "name",
                   "operator": "eq",
                   "value": portaluser.usrName
               }]
           };
           let record = db.object('PortalUser').queryByCondition(condition, option);
           if (record && record.length > 0) {
               console.log("已存在，不再创建");
               return record[0].id;
           }
           // 插入数据
           let roleId = portaluser.roleId;
           delete portaluser.roleId; //非portaluser字段，保存后删除
           let portaluserId = db.object('PortalUser').insert(portaluser);
           if (!roleId) {
               return portaluserId;
           }
           db.setup('roleportaluser').insert({
               "portaluser": portaluserId,
               "role": roleId
           });
           return portaluserId;
       }
       // 业务自己开发查询逻辑，查询第三方系统的用户，并添加到平台portaluser表, 可以参考帮助文档对接oneaccess示例
       private queryUsers(token: string): Array<any> {
           // 这里写调用三方接口获取用户列表的逻辑
           let req: http.Request = {
               headers: {
                   "content-type": "application/json",
                   "Authorization": "Bearer " + token
               },
               params: {
                   "limit": 100, // 大于100需要做分页遍历查询所有页
                   "offset": 0,
               }
           };
           let result = this.sendRequest("https://test.example.com/api/v2/tenant/users", "GET", req);
           if (result.error_code) {
               throw new Error(result.error_msg);
           }
           return result && result.users || [];
       }
       private queryRoleByName(name: string): any {
           let option = {};
           let condition = {
               "conjunction": "AND",
               "conditions": [{
                   "field": "name",
                   "operator": "eq",
                   "value": name
               }]
           };
           let records = db.setup('role').queryByCondition(condition, option);
           if (records && records.length > 0) {
               console.log("已存在，不再创建");
               return records[0];
           }
           return null;
       }
       private addRole(role: StructRole): string {
           // 校验记录是否已经存在
           let record = this.queryRoleByName(role.name);
           if (record) {
               console.log("已存在，不再创建");
               return record.id;
           }
           // 插入数据
           return db.setup('role').insert(role);
       }
       // 业务自己开发查询逻辑，查询第三方系统的组织机构逻辑, 并添加到平台role表，可以参考帮助文档对接oneaccess示例，查询首次组织
       private queryOrgs(token: string, org_id?: string): Array<any> {
           // 这里写调用三方接口获取组织结构的逻辑
           let level0Orgs = this.getOrgList(100, 0, org_id, token);
           if (level0Orgs && level0Orgs.organizations) {
               return level0Orgs.organizations;
           }
           return [];
       }
       // 同步某一组织，已经组织下子组织
       private syncOrg(org: any, token: string, reportTo?: string) {
           console.log(org)
           let role = new StructRole();
           role.name = "oneaccess" + org.org_id;
           role.label = org.name;
           console.log(reportTo)
           if (reportTo) {
               role.reportTo = reportTo;
           }
           let parentRoleId = this.addRole(role)
           let childOrgs = this.queryOrgs(token, org.org_id);
           console.log(childOrgs);
           for (let childOrg of childOrgs) {
               if (childOrg.parent_id === org.org_id) {
                   this.syncOrg(childOrg, token, parentRoleId)
               }
           }
       }
       // oneaccess查询组织机构的方法，对接其他第三方需要重写
       private getOrgList(limit: number, offset: number, org_id: string, token: string): any {
           // 这里写调用三方接口获取组织结构的逻辑
           let req: http.Request = {
               headers: {
                   "content-type": "application/json",
                   "Authorization": "Bearer " + token
               },
               params: {
                   "limit": limit,
                   "offset": offset,
                   "org_id": org_id,
                   "all_child": false
               }
           };
           let result = this.sendRequest("https://test.example.com/api/v2/tenant/organizations", "GET", req);
           if (result.error_code) {
               throw new Error(result.error_msg);
           }
           return result;
       }
       private sendRequest(url: string, method: string, callOptions?: http.Request): any {
           let client = http.newClient();
           let resp;
           if (method === "GET") {
               resp = client.get(url, callOptions);
           } else {
               resp = client.post(url, callOptions);
           }
           let result = iconv.decode(resp.data, Encoding.Utf8);
           return JSON.parse(result);
       }
       // 获取第三方系统的接口调用凭证，需要业务根据第三方接口适配开发
       private getToken(): string {
           let req = {
               headers: {
                   'Content-Type': "application/x-www-form-urlencoded"
               },
               params: {
                   "client_id": "o8XvdwMF7******KLxVzoxarXr",
                   "client_secret": "uf8vBFR1RMAf******Uq31NThCzT1OOAlepsM00",
                   "grant_type": "client_credentials",
               }
           };
           let result = this.sendRequest('https://test.example.com/api/v2/tenant/token', "POST", req);
           if (result.error) {
               throw new Error(result.error);
           }
           return result.access_token;
       }
   }
   ```
   
   
7. 单击"去同步"，同步组织机构和用户信息，支持立即同步和设置定时同步任务两种方式。 
   图5同步组织机构和用户信息   
   ![](https://support.huaweicloud.com/usermanual-astrozero/zh-cn_image_0000001894298780.png "点击放大")
   - 立即同步
     1. 单击"同步部门"下的"立即同步"，在弹框中，若勾选"同时清除未包含在同步中的部门"表示在华为云Astro轻应用中清除第三方中已删除的部门，单击"确定"。
     
     2. 单击"同步用户"下的"立即同步"，在弹框中，勾选"同时清除未包含在同步中的用户"表示在华为云Astro轻应用中清除第三方中已删除的用户，单击"确定"。
      
   
   - 设置定时任务实现自动同步
     1. 在"同步部门"后，打开"开启自动同步"开关。单击"同步部门"下的"自动同步设置"，设置首次同步时间、执行周期，勾选"同时清除未包含在同步中的部门"表示在华为云Astro轻应用中清除第三方中已删除的部门，单击"确定"。
     
     2. 在"同步用户"后，打开"开启自动同步"开关。单击"同步用户"下的"自动同步设置"，设置首次同步时间、执行周期，勾选"同时清除未包含在同步中的用户"表示在华为云Astro轻应用中清除第三方中已删除的用户，单击"确定"。
      
    
   系统会同步第三方机构组织信息到华为云Astro轻应用业务配置中心的"组织用户 \> 组织机构"中，并同步第三方用户信息到华为云Astro轻应用业务配置中心的"组织用户 \> 用户管理"中。
   
   
8. （可选）在"认证配置"菜单中，单击"下载"，下载SP Metadata文件。 
   ![](https://support.huaweicloud.com/usermanual-astrozero/public_sys-resources/note_3.0-zh-cn.png)
   - 后续需要配置该文件到身份提供商中。
   
   - 当[5]中认证协议选择"SAML2"时，才需要执行此步骤。
    
   
   
 
