当前位置:首页 » 《休闲阅读》 » 正文

【DataSophon】DataSophon1.2.1 ranger usersync整合

12 人参与  2024年11月10日 14:03  分类 : 《休闲阅读》  评论

点击全文阅读


 目录

一、简介

二、实现步骤

2.1 ranger-usersync包下载编译

2.2 构建压缩包

2.3 编辑元数据文件

2.4 修改源码

三、重新安装


一、简介


如下是DDP1.2.1默认有的rangerAdmin, 我们需要将rangerusersync整合进来 ,实现将Linux机器上的用户和组信息同步到RangerAdmin的数据库中进行管理。


二、实现步骤


2.1 ranger-usersync包下载编译


ranger官网tar包下载

https://ranger.apache.org/download.html

自己编译 或者网上下载

参考文章:

Apache Ranger - Download Apache Ranger?

Ranger安装和使用-CSDN博客

https://juejin.cn/post/6844904159930482696

https://zhuanlan.zhihu.com/p/562012618

权限管理Ranger详解_大数据权限管理利器 - ranger-CSDN博客

2.2 构建压缩包


将ranger-usersync安装包集成到ranger组件中重新打包,如下是ranger admin包和ranger-usersync包。

# 解压ranger组件原有包tar -zxvf ranger-2.1.0.tar.gzcd ranger-2.1.0# 将编译好的的sync安装包解压到当前目录tar -zxvf ranger-2.1.0-usersync.tar.gz ./cd ranger-2.1.0-usersyncvim ranger_usersync.sh
#!/bin/bash# 获取脚本当前目录current_path=$(dirname "$0")# 使用说明usage="Usage: $0 {start|stop|status|restart}"start(){    echo "ranger userSync start"    sh "$current_path/ranger-usersync" start    if [ $? -eq 0 ]; then        echo "ranger userSync start success"    else        echo "ranger userSync start failed"        exit 1    fi}stop(){    echo "ranger userSync stop"    sh "$current_path/ranger-usersync" stop    if [ $? -eq 0 ]; then        echo "ranger userSync stop success"    else        echo "ranger userSync stop failed"        exit 1    fi}status(){    process_name="UnixAuthenticationService"    # 使用 pgrep 命令检测进程是否存在    pgrep -f "$process_name" > /dev/null    if [ $? -eq 0 ]; then        echo "进程 $process_name 存在"        exit 0    else        echo "进程 $process_name 不存在"        exit 1    fi}restart(){    echo "ranger userSync restart"    sh "$current_path/ranger-usersync" restart    if [ $? -eq 0 ]; then        echo "ranger userSync restart success"    else        echo "ranger userSync restart failed"        exit 1    fi}# 处理参数startStop=$1case $startStop in    start)        start        ;;    stop)        stop        ;;    status)        status        ;;    restart)        restart        ;;    *)        echo "$usage"        exit 1        ;;esacecho "End $startStop ranger userSync"

打包

tar -zcvf ranger-2.1.0.tar.gz ranger-2.1.0md5sum ranger-2.1.0.tar.gzecho '756fa828e02d8f890ca2165d237ef487' > ranger-2.1.0.tar.gz.md5cp ranger-2.1.0.tar.gz ranger-2.1.0.tar.gz.md5 /opt/datasophon/DDP/packages/

2.3 编辑元数据文件


ranger安装配置文件

vim /opt/datasophon/DDP/packages/datasophon-manager-1.2.1/conf/meta/DDP-1.2.1/RANGER/service_ddl.json
{  "name": "RANGER",  "label": "Ranger",  "description": "权限控制框架",  "version": "2.1.0",  "sortNum": 10,  "dependencies":[],  "packageName": "ranger-2.1.0.tar.gz",  "decompressPackageName": "ranger-2.1.0",  "roles": [    {      "name": "RangerAdmin",      "label": "RangerAdmin",      "roleType": "master",      "cardinality": "1",      "logFile": "/var/log/ranger/admin/ranger-admin-${host}-root.log",      "jmxPort": 6081,      "sortNum": 1,      "startRunner": {        "timeout": "60",        "program": "bin/ranger_admin.sh",        "args": [          "start"        ]      },      "stopRunner": {        "timeout": "600",        "program": "bin/ranger_admin.sh",        "args": [          "stop"        ]      },      "statusRunner": {        "timeout": "60",        "program": "bin/ranger_admin.sh",        "args": [          "status"        ]      },      "externalLink": {        "name": "RangerAdmin Ui",        "label": "RangerAdmin Ui",        "url": "http://${host}:6080"      }    },    {      "name": "RangerUsersync",      "label": "RangerUsersync",      "roleType": "master",      "runAs": {        "user": "root",        "group": "root"      },      "cardinality": "1",      "logFile": "ranger-2.1.0-usersync/logs/usersync-${host}-ranger.log",      "jmxPort": "",      "sortNum": 2,      "startRunner": {        "timeout": "60",        "program": "ranger-2.1.0-usersync/ranger_usersync.sh",        "args": [          "start"        ]      },      "stopRunner": {        "timeout": "600",        "program": "ranger-2.1.0-usersync/ranger_usersync.sh",        "args": [          "stop"        ]      },      "statusRunner": {        "timeout": "60",        "program": "ranger-2.1.0-usersync/ranger_usersync.sh",        "args": [          "status"        ]      },      "restartRunner": {        "timeout": "60",        "program": "ranger-2.1.0-usersync/ranger_usersync.sh",        "args": [          "restart"        ]      }    }  ],  "configWriter": {    "generators": [      {        "filename": "install.properties",        "configFormat": "custom",        "templateName": "ranger-install.ftl",        "outputDirectory": "",        "includeParams": [          "rootPassword",          "dbHost",          "database",          "rangerUser",          "rangerPassword",          "rangerAdminUrl",          "enableHDFSPlugin",          "enableHIVEPlugin",          "enableHBASEPlugin",          "spnegoPrincipal",          "spnegoKeytab",          "adminPrincipal",          "adminKeytab",          "hadoopHome",          "rangerHome"        ]      },      {        "filename": "install.properties1",        "configFormat": "custom",        "templateName": "ranger-usersync-install.ftl",        "outputDirectory": "ranger-2.1.0-usersync",        "includeParams": [          "rangerAdminUrl",          "adminPrincipal",          "adminKeytab",          "hadoopHome",          "syncInterval"        ]      }    ]  },  "parameters": [    {      "name": "rootPassword",      "label": "数据库root用户密码",      "description": "",      "required": true,      "configType": "map",      "type": "input",      "value": "",      "configurableInWizard": true,      "hidden": false,      "defaultValue": "123456"    },    {      "name": "dbHost",      "label": "数据库地址",      "description": "",      "required": true,      "configType": "map",      "type": "input",      "value": "",      "configurableInWizard": true,      "hidden": false,      "defaultValue": "${apiHost}"    },{      "name": "database",      "label": "数据库名",      "description": "",      "required": true,      "configType": "map",      "type": "input",      "value": "",      "configurableInWizard": true,      "hidden": false,      "defaultValue": "ranger"    },    {      "name": "rangerUser",      "label": "Ranger数据库用户",      "description": "",      "required": true,      "configType": "map",      "type": "input",      "value": "",      "configurableInWizard": true,      "hidden": false,      "defaultValue": "ranger"    },{      "name": "rangerPassword",      "label": "Ranger数据库密码",      "description": "",      "required": true,      "configType": "map",      "type": "input",      "value": "",      "configurableInWizard": true,      "hidden": false,      "defaultValue": "ranger"    },    {      "name": "rangerAdminUrl",      "label": "Ranger访问地址",      "description": "",      "required": true,      "configType": "map",      "type": "input",      "value": "",      "configurableInWizard": true,      "hidden": false,      "defaultValue": "${rangerAdminUrl}"    },    {      "name": "enableHDFSPlugin",      "label": "启用HDFS Ranger插件",      "description": "",      "required": true,      "type": "switch",      "value": false,      "configurableInWizard": true,      "hidden": false,      "defaultValue": false    },    {      "name": "enableHIVEPlugin",      "label": "启用Hive Ranger插件",      "description": "",      "required": true,      "type": "switch",      "value": false,      "configurableInWizard": true,      "hidden": false,      "defaultValue": false    },    {      "name": "enableHBASEPlugin",      "label": "启用Hbase Ranger插件",      "description": "",      "required": true,      "type": "switch",      "value": false,      "configurableInWizard": true,      "hidden": false,      "defaultValue": false    },    {      "name": "enableKerberos",      "label": "开启Kerberos认证",      "description": "开启Kerberos认证",      "required": false,      "type": "switch",      "value": false,      "configurableInWizard": true,      "hidden": true,      "defaultValue": false    },    {      "name": "spnegoPrincipal",      "label": "Spnego Principal",      "description": "",      "configWithKerberos": true,      "required": false,      "configType": "map",      "type": "input",      "value": "HTTP/${host}@HADOOP.COM",      "configurableInWizard": true,      "hidden": true,      "defaultValue": "HTTP/${host}@HADOOP.COM"    },    {      "name": "spnegoKeytab",      "label": "Spnego Keytab",      "description": "",      "configWithKerberos": true,      "required": false,      "configType": "map",      "type": "input",      "value": "/etc/security/keytab/spnego.service.keytab",      "configurableInWizard": true,      "hidden": true,      "defaultValue": "/etc/security/keytab/spnego.service.keytab"    },    {      "name": "adminPrincipal",      "label": "Ranger Admin Principal",      "description": "",      "configWithKerberos": true,      "required": false,      "configType": "map",      "type": "input",      "value": "rangeradmin/${host}@HADOOP.COM",      "configurableInWizard": true,      "hidden": true,      "defaultValue": "rangeradmin/${host}@HADOOP.COM"    },    {      "name": "adminKeytab",      "label": "Ranger Admin Keytab",      "description": "",      "configWithKerberos": true,      "required": false,      "configType": "map",      "type": "input",      "value": "/etc/security/keytab/rangeradmin.keytab",      "configurableInWizard": true,      "hidden": true,      "defaultValue": "/etc/security/keytab/rangeradmin.keytab"    },    {      "name": "hadoopHome",      "label": "HADOOP_HOME",      "description": "",      "configWithKerberos": true,      "required": true,      "configType": "map",      "type": "input",      "value": "${HADOOP_HOME}",      "configurableInWizard": true,      "hidden": true,      "defaultValue": "${HADOOP_HOME}"    },    {      "name": "rangerHome",      "label": "RANGER_HOME",      "description": "",      "required": true,      "configType": "map",      "type": "input",      "value": "${RANGER_HOME}",      "configurableInWizard": true,      "hidden": false,      "defaultValue": "${RANGER_HOME}"    },    {      "name": "syncInterval",      "label": "SYNC_INTERVAL",      "description": "userSync同步间隔时间,单位(分钟)",      "required": true,      "configType": "map",      "type": "input",      "value": "1",      "configurableInWizard": true,      "hidden": false,      "defaultValue": "1"    }  ]}

各worker元数据文件,已部署的路径:

vim /opt/datasophon/datasophon-worker/conf/templates/ranger-usersync-install.ftl

ranger配置文件 install.properties ,使用了 SYNC_SOURCE = unix

# Licensed to the Apache Software Foundation (ASF) under one or more# contributor license agreements.  See the NOTICE file distributed with# this work for additional information regarding copyright ownership.# The ASF licenses this file to You under the Apache License, Version 2.0# (the "License"); you may not use this file except in compliance with# the License.  You may obtain a copy of the License at##     http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.# The base path for the usersync processranger_base_dir = /etc/ranger## The following URL should be the base URL for connecting to the policy manager web application# For example:##  POLICY_MGR_URL = http://policymanager.xasecure.net:6080#POLICY_MGR_URL = ${rangerAdminUrl}# sync source,  only unix and ldap are supported at present# defaults to unixSYNC_SOURCE = unix## Minimum Unix User-id to start SYNC.# This should avoid creating UNIX system-level users in the Policy Manager#MIN_UNIX_USER_ID_TO_SYNC = 500# Minimum Unix Group-id to start SYNC.# This should avoid creating UNIX system-level users in the Policy Manager#MIN_UNIX_GROUP_ID_TO_SYNC = 500# sync interval in minutes# user, groups would be synced again at the end of each sync interval# defaults to 5   if SYNC_SOURCE is unix# defaults to 360 if SYNC_SOURCE is ldapSYNC_INTERVAL = ${syncInterval}#User and group for the usersync processunix_user=rangerunix_group=ranger#change password of rangerusersync user. Please note that this password should be as per rangerusersync user in rangerrangerUsersync_password=admin123#Set to run in kerberos environmentusersync_principal=<#if adminPrincipal??>${adminPrincipal}</#if>usersync_keytab=<#if adminKeytab??>${adminKeytab}</#if>hadoop_conf=${hadoopHome}/etc/hadoop/conf## The file where all credential is kept in cryptic format#CRED_KEYSTORE_FILENAME=/etc/ranger/usersync/conf/rangerusersync.jceks# SSL AuthenticationAUTH_SSL_ENABLED=falseAUTH_SSL_KEYSTORE_FILE=/etc/ranger/usersync/conf/cert/unixauthservice.jksAUTH_SSL_KEYSTORE_PASSWORD=UnIx529pAUTH_SSL_TRUSTSTORE_FILE=AUTH_SSL_TRUSTSTORE_PASSWORD=# ---------------------------------------------------------------# The following properties are relevant only if SYNC_SOURCE = ldap# ---------------------------------------------------------------# The below properties ROLE_ASSIGNMENT_LIST_DELIMITER, USERS_GROUPS_ASSIGNMENT_LIST_DELIMITER, USERNAME_GROUPNAME_ASSIGNMENT_LIST_DELIMITER,#and GROUP_BASED_ROLE_ASSIGNMENT_RULES can be used to assign role to LDAP synced users and groups#NOTE all the delimiters should have different values and the delimiters should not contain characters that are allowed in userName or GroupName# default value ROLE_ASSIGNMENT_LIST_DELIMITER = &ROLE_ASSIGNMENT_LIST_DELIMITER = &#default value USERS_GROUPS_ASSIGNMENT_LIST_DELIMITER = :USERS_GROUPS_ASSIGNMENT_LIST_DELIMITER = :#default value USERNAME_GROUPNAME_ASSIGNMENT_LIST_DELIMITER = ,USERNAME_GROUPNAME_ASSIGNMENT_LIST_DELIMITER = ,# with above mentioned delimiters a sample value would be ROLE_SYS_ADMIN:u:userName1,userName2&ROLE_SYS_ADMIN:g:groupName1,groupName2&ROLE_KEY_ADMIN:u:userName&ROLE_KEY_ADMIN:g:groupName&ROLE_USER:u:userName3,userName4&ROLE_USER:g:groupName3#&ROLE_ADMIN_AUDITOR:u:userName&ROLE_KEY_ADMIN_AUDITOR:u:userName&ROLE_KEY_ADMIN_AUDITOR:g:groupName&ROLE_ADMIN_AUDITOR:g:groupNameGROUP_BASED_ROLE_ASSIGNMENT_RULES =# URL of source ldap# a sample value would be:  ldap://ldap.example.com:389# Must specify a value if SYNC_SOURCE is ldapSYNC_LDAP_URL =# ldap bind dn used to connect to ldap and query for users and groups# a sample value would be cn=admin,ou=users,dc=hadoop,dc=apache,dc=org# Must specify a value if SYNC_SOURCE is ldapSYNC_LDAP_BIND_DN =# ldap bind password for the bind dn specified above# please ensure read access to this file  is limited to root, to protect the password# Must specify a value if SYNC_SOURCE is ldap# unless anonymous search is allowed by the directory on users and groupSYNC_LDAP_BIND_PASSWORD =# ldap delta sync flag used to periodically sync users and groups based on the updates in the server# please customize the value to suit your deployment# default value is set to true when is SYNC_SOURCE is ldapSYNC_LDAP_DELTASYNC =# search base for users and groups# sample value would be dc=hadoop,dc=apache,dc=orgSYNC_LDAP_SEARCH_BASE =# search base for users# sample value would be ou=users,dc=hadoop,dc=apache,dc=org# overrides value specified in SYNC_LDAP_SEARCH_BASESYNC_LDAP_USER_SEARCH_BASE = # search scope for the users, only base, one and sub are supported values# please customize the value to suit your deployment# default value: subSYNC_LDAP_USER_SEARCH_SCOPE = sub# objectclass to identify user entries# please customize the value to suit your deployment# default value: personSYNC_LDAP_USER_OBJECT_CLASS = person# optional additional filter constraining the users selected for syncing# a sample value would be (dept=eng)# please customize the value to suit your deployment# default value is emptySYNC_LDAP_USER_SEARCH_FILTER =# attribute from user entry that would be treated as user name# please customize the value to suit your deployment# default value: cnSYNC_LDAP_USER_NAME_ATTRIBUTE = cn# attribute from user entry whose values would be treated as# group values to be pushed into Policy Manager database# You could provide multiple attribute names separated by comma# default value: memberof, ismemberofSYNC_LDAP_USER_GROUP_NAME_ATTRIBUTE = memberof,ismemberof## UserSync - Case Conversion Flags# possible values:  none, lower, upperSYNC_LDAP_USERNAME_CASE_CONVERSION=lowerSYNC_LDAP_GROUPNAME_CASE_CONVERSION=lower#user sync log pathlogdir=logs#/var/log/ranger/usersync# PID DIR PATHUSERSYNC_PID_DIR_PATH=/var/run/ranger# do we want to do ldapsearch to find groups instead of relying on user entry attributes# valid values: true, false# any value other than true would be treated as false# default value: falseSYNC_GROUP_SEARCH_ENABLED=# do we want to do ldapsearch to find groups instead of relying on user entry attributes and# sync memberships of those groups# valid values: true, false# any value other than true would be treated as false# default value: falseSYNC_GROUP_USER_MAP_SYNC_ENABLED=# search base for groups# sample value would be ou=groups,dc=hadoop,dc=apache,dc=org# overrides value specified in SYNC_LDAP_SEARCH_BASE,  SYNC_LDAP_USER_SEARCH_BASE# if a value is not specified, takes the value of  SYNC_LDAP_SEARCH_BASE# if  SYNC_LDAP_SEARCH_BASE is also not specified, takes the value of SYNC_LDAP_USER_SEARCH_BASESYNC_GROUP_SEARCH_BASE=# search scope for the groups, only base, one and sub are supported values# please customize the value to suit your deployment# default value: subSYNC_GROUP_SEARCH_SCOPE=# objectclass to identify group entries# please customize the value to suit your deployment# default value: groupofnamesSYNC_GROUP_OBJECT_CLASS=# optional additional filter constraining the groups selected for syncing# a sample value would be (dept=eng)# please customize the value to suit your deployment# default value is emptySYNC_LDAP_GROUP_SEARCH_FILTER=# attribute from group entry that would be treated as group name# please customize the value to suit your deployment# default value: cnSYNC_GROUP_NAME_ATTRIBUTE=# attribute from group entry that is list of members# please customize the value to suit your deployment# default value: memberSYNC_GROUP_MEMBER_ATTRIBUTE_NAME=# do we want to use paged results control during ldapsearch for user entries# valid values: true, false# any value other than true would be treated as false# default value: true# if the value is false, typical AD would not return more than 1000 entriesSYNC_PAGED_RESULTS_ENABLED=# page size for paged results control# search results would be returned page by page with the specified number of entries per page# default value: 500SYNC_PAGED_RESULTS_SIZE=#LDAP context referral could be ignore or followSYNC_LDAP_REFERRAL = ignore# if you want to enable or disable jvm metrics for usersync process# valid values: true, false# any value other than true would be treated as false# default value: false# if the value is false, jvm metrics is not createdJVM_METRICS_ENABLED=# filename of jvm metrics created for usersync process# default value: ranger_usersync_metric.jsonJVM_METRICS_FILENAME=#file directory for jvm metrics# default value : logdirJVM_METRICS_FILEPATH=#frequency for jvm metrics to be updated# default value : 10000 millisecondsJVM_METRICS_FREQUENCY_TIME_IN_MILLIS=

2.4 修改源码


com.datasophon.worker.strategy.RangerAdminHandlerStrategy

/* *  Licensed to the Apache Software Foundation (ASF) under one or more *  contributor license agreements.  See the NOTICE file distributed with *  this work for additional information regarding copyright ownership. *  The ASF licenses this file to You under the Apache License, Version 2.0 *  (the "License"); you may not use this file except in compliance with *  the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * *  Unless required by applicable law or agreed to in writing, software *  distributed under the License is distributed on an "AS IS" BASIS, *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *  See the License for the specific language governing permissions and *  limitations under the License. */package com.datasophon.worker.strategy;import cn.hutool.core.io.FileUtil;import com.datasophon.common.Constants;import com.datasophon.common.cache.CacheUtils;import com.datasophon.common.command.ServiceRoleOperateCommand;import com.datasophon.common.enums.CommandType;import com.datasophon.common.utils.ExecResult;import com.datasophon.common.utils.ShellUtils;import com.datasophon.worker.handler.ServiceHandler;import com.datasophon.worker.utils.KerberosUtils;import java.util.ArrayList;public class RangerAdminHandlerStrategy extends AbstractHandlerStrategy implements ServiceRoleStrategy {    public RangerAdminHandlerStrategy(String serviceName, String serviceRoleName) {        super(serviceName, serviceRoleName);    }    @Override    public ExecResult handler(ServiceRoleOperateCommand command) {        String workPath = Constants.INSTALL_PATH + Constants.SLASH + command.getDecompressPackageName();        ExecResult startResult = new ExecResult();        ServiceHandler serviceHandler = new ServiceHandler(command.getServiceName(), command.getServiceRoleName());        if (command.getEnableKerberos()) {            logger.info("start to get ranger keytab file");            String hostname = CacheUtils.getString(Constants.HOSTNAME);            KerberosUtils.createKeytabDir();            if (!FileUtil.exist("/etc/security/keytab/spnego.service.keytab")) {                KerberosUtils.downloadKeytabFromMaster("HTTP/" + hostname, "spnego.service.keytab");            }            if (!FileUtil.exist("/etc/security/keytab/rangeradmin.keytab")) {                KerberosUtils.downloadKeytabFromMaster("rangeradmin/" + hostname, "rangeradmin.keytab");            }        }        if (command.getCommandType().equals(CommandType.INSTALL_SERVICE) && command.getServiceRoleName().equals("RangerUsersync")) {            ShellUtils.exceShell("mv " + workPath + "/ranger-2.1.0-usersync/install.properties1 " + workPath + "/ranger-2.1.0-usersync/install.properties");            ShellUtils.exceShell("chmod 755 " + workPath + "/ranger-2.1.0-usersync/install.properties");            logger.info("setup ranger user sync");            ArrayList<String> commands = new ArrayList<>();            commands.add("sh");            commands.add("./setup.sh");            ExecResult execResult = ShellUtils.execWithStatus(workPath + "/ranger-2.1.0-usersync", commands, 300L, logger);            if (execResult.getExecResult()) {                logger.info("setup ranger user sync success");            } else {                logger.info("setup ranger user sync failed");                return execResult;            }            ShellUtils.exceShell("sed -i '/<name>ranger\\.usersync\\.enabled<\\/name>/{n;s/<value>false<\\/value>/<value>true<\\/value>/}' "                    + workPath +                    "/ranger-2.1.0-usersync/conf/ranger-ugsync-site.xml");            startResult = serviceHandler.start(command.getStartRunner(), command.getStatusRunner(),                    command.getDecompressPackageName(), command.getRunAs());        } else {            startResult = serviceHandler.start(command.getStartRunner(), command.getStatusRunner(),                    command.getDecompressPackageName(), command.getRunAs());        }        return startResult;    }}

com.datasophon.worker.strategy.ServiceRoleStrategyContext

map.put("RangerUsersync", new RangerAdminHandlerStrategy("RANGER", "RangerUsersync"));

datasophon-worker jar包更新

mv datasophon-worker-1.2.1.jar      /opt/datasophon/datasophon-worker/lib/


三、重新安装


添加ranger服务

分配服务Master角色

服务配置

选择"settings"我们可以看到linux 上的用户已同步成功。


点击全文阅读


本文链接:http://zhangshiyu.com/post/184261.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1