将登录角色添加到 PostgreSQL

在 Standard 或 Advanced 许可等级下可用。

PostgreSQL 使用角色登录到数据库集群和数据库。每个用户均称为登录角色。对于将拥有地理数据库对象的所有登录角色,还必须在该数据库中创建方案。要通过 ArcGIS 使用 PostgreSQL,该方案名称必须与登录角色名称相同,并且归此登录角色所有。

可使用创建数据库用户工具添加可创建表和要素类的登录角色。此工具将在 PostgreSQL 数据库集群中创建登录角色、为您所指定的数据库中的用户创建匹配方案以及将新方案的 usage 权限授予给公共角色。

如果想要创建不具有方案从而无法在地理数据库中创建对象的登录角色,可使用 PostgreSQL 客户端应用程序(如 pgAdmin 或 PL/pgSQL)在 PostgreSQL 数据库集群中创建角色。

您还可以创建可向其中添加登录角色的组角色。然后,可以指定对将要应用于所有相关联登录角色的组的权限。可使用创建角色工具或脚本创建组角色,或者也可以使用 SQL

注:

还必须为组中每个将拥有地理数据库对象的登录角色创建匹配方案。无法为组角色创建方案。

添加可创建数据库对象的用户

您可以运行 ArcGIS Desktop 中的创建数据库用户工具或调用 Python 脚本中的工具来创建数据库用户,该用户可创建表、要素类以及视图。

要运行创建数据库用户工具,您必须使用具有超级用户身份的角色连接到数据库。

使用创建数据库用户工具

  1. 启动 ArcGIS Desktop 客户端。
  2. 使用具有 PostgreSQL 超级用户权限的角色连接到数据库或地理数据库。
  3. 打开创建数据库用户工具。

    该工具位于“数据管理”工具箱的“地理数据库管理”工具集中。

  4. 指定输入数据库连接的数据库连接。
  5. 为此工具将要创建的登录角色和方案输入名称。
  6. 为数据库用户输入密码。
  7. 如果您已具有组角色并希望此用户成为该组的成员,请指定该用户的角色。
  8. 单击确定 (ArcMap) 或运行 (ArcGIS Pro)。

运行 Python 脚本

若要编写用户创建的脚本,请按照以下步骤操作:

  1. 在 ArcGIS 客户端计算机上创建文本文件,然后将以下脚本复制到此文件。

    """
    Name: create_database_user.py
    Description: Provide connection information to a database user.
    Type create_database_user.py -h or create_database_user.py --help for usage
    """
    
    # Import system modules
    import arcpy
    import os
    import optparse
    import sys
    
    
    # Define usage and version
    parser = optparse.OptionParser(usage = "usage: %prog [Options]", version="%prog 1.0 for 10.1 release")
    
    #Define help and options
    parser.add_option ("--DBMS", dest="Database_type", type="choice", choices=['SQLSERVER', 'ORACLE', 'POSTGRESQL', ''], default="", help="Type of enterprise DBMS:  SQLSERVER, ORACLE, or POSTGRESQL.")                   
    parser.add_option ("-i", dest="Instance", type="string", default="", help="DBMS instance name")
    parser.add_option ("-D", dest="Database", type="string", default="none", help="Database name:  Not required for Oracle")
    parser.add_option ("--auth", dest="Account_authentication", type ="choice", choices=['DATABASE_AUTH', 'OPERATING_SYSTEM_AUTH'], default='DATABASE_AUTH', help="Authentication type options (case-sensitive):  DATABASE_AUTH, OPERATING_SYSTEM_AUTH.  Default=DATABASE_AUTH")
    parser.add_option ("-U", dest="Dbms_admin", type="string", default="", help="DBMS administrator user")
    parser.add_option ("-P", dest="Dbms_admin_pwd", type="string", default="", help="DBMS administrator password")
    parser.add_option ("--utype", dest="user_type", type ="choice", choices=['DATABASE_USER', 'OPERATING_SYSTEM_USER'], default='DATABASE_USER', help="Authentication type options (case-sensitive):  DATABASE_USER, OPERATING_SYSTEM_USER.  Default=DATABASE_USER")
    parser.add_option ("-u", dest="dbuser", type="string", default="", help="database user name")
    parser.add_option ("-p", dest="dbuser_pwd", type="string", default="", help="database user password")
    parser.add_option ("-r", dest="role", type="string", default="", help="role to be granted to the user")
    parser.add_option ("-t", dest="Tablespace", type="string", default="", help="Tablespace name")
    # Check if value entered for option
    try:
    	(options, args) = parser.parse_args()
    
    	#Check if no system arguments (options) entered
    	if len(sys.argv) == 1:
    		print "%s: error: %s\n" % (sys.argv[0], "No command options given")
    		parser.print_help()
    		sys.exit(3)
    
    	#Usage parameters for spatial database connection
    	database_type = options.Database_type.upper()
    	instance = options.Instance
    	database = options.Database.lower()	
    	account_authentication = options.Account_authentication.upper()
    	dbms_admin = options.Dbms_admin
    	dbms_admin_pwd = options.Dbms_admin_pwd
    	dbuser = options.dbuser
    	dbuser_pwd = options.dbuser_pwd	
    	tablespace = options.Tablespace
    	user_type = options.user_type
    	role = options.role
    
    	
    	if (database_type == "SQLSERVER"):
    		database_type = "SQL_SERVER"
    	
    	if( database_type ==""):	
    		print(" \n%s: error: \n%s\n" % (sys.argv[0], "DBMS type (--DBMS) must be specified."))
    		parser.print_help()
    		sys.exit(3)		
    	
    	if(database_type == "SQL_SERVER"):
    		if( account_authentication == "DATABASE_AUTH" and dbms_admin == ""):
    			print("\n%s: error: %s\n" % (sys.argv[0], "DBMS administrator must be specified with database authentication"))
    			sys.exit(3)
    		if( account_authentication == "OPERATING_SYSTEM_AUTH" and dbms_admin != ""):
    			print("\nWarning: %s\n" % ("Ignoring DBMS administrator specified when using operating system authentication..."))
    	else:		
    		if( dbuser.lower() == ""):
    			print("\n%s: error: %s\n" % (sys.argv[0], "Database user must be specified."))
    			sys.exit(3)		
    		if( dbms_admin == ""):
    			print("\n%s: error: %s\n" % (sys.argv[0], "DBMS administrator must be specified!"))
    			sys.exit(3)
    
    	if ( user_type == "DATABASE_USER" and (dbuser =="" or dbuser_pwd =="")):
    		print(" \n%s: error: \n%s\n" % (sys.argv[0], "To create database authenticated user, user name and password must be specified!"))
    		parser.print_help()
    		sys.exit(3)	
    
    	# Get the current product license
    	product_license=arcpy.ProductInfo()
    	
    	# Checks required license level
    	if product_license.upper() == "ARCVIEW" or product_license.upper() == 'ENGINE':
    		print("\n" + product_license + " license found!" + "  Creating a user in an enterprise geodatabase or database requires an ArcGIS Desktop Standard or Advanced, ArcGIS Engine with the Geodatabase Update extension, or ArcGIS Server license.")
    		sys.exit("Re-authorize ArcGIS before creating a database user.")
    	else:
    		print("\n" + product_license + " license available!  Continuing to create...")
    		arcpy.AddMessage("+++++++++")
    
    	# Local variables
    	instance_temp = instance.replace("\\","_")
    	instance_temp = instance_temp.replace("/","_")
    	instance_temp = instance_temp.replace(":","_")
    	Conn_File_NameT = instance_temp + "_" + database + "_" + dbms_admin   
    
    	if os.environ.get("TEMP") == None:
    		temp = "c:\\temp"	
    	else:
    		temp = os.environ.get("TEMP")
    	
    	if os.environ.get("TMP") == None:
    		temp = "/usr/tmp"		
    	else:
    		temp = os.environ.get("TMP")  
    
    	Connection_File_Name = Conn_File_NameT + ".sde"
    	Connection_File_Name_full_path = temp + os.sep + Conn_File_NameT + ".sde"
    	
    	# Check for the .sde file and delete it if present
    	arcpy.env.overwriteOutput=True
    	if os.path.exists(Connection_File_Name_full_path):
    		os.remove(Connection_File_Name_full_path)
    
    	try:
    		print("\nCreating Database Connection File...\n")
    		# Process: Create Database Connection File...
    		# Usage:  out_file_location, out_file_name, DBMS_TYPE, instnace, database, account_authentication, username, password, save_username_password(must be true)
    		#arcpy.CreateDatabaseConnection_management(temp , Connection_File_Name, database_type, instance, database, account_authentication, dbms_admin, dbms_admin_pwd, "TRUE")
    		arcpy.CreateDatabaseConnection_management(out_folder_path=temp, out_name=Connection_File_Name, database_platform=database_type, instance=instance, database=database, account_authentication=account_authentication, username=dbms_admin, password=dbms_admin_pwd, save_user_pass="TRUE")
    	        for i in range(arcpy.GetMessageCount()):
    			if "000565" in arcpy.GetMessage(i):   #Check if database connection was successful
    				arcpy.AddReturnMessage(i)
    				arcpy.AddMessage("\n+++++++++")
    				arcpy.AddMessage("Exiting!!")
    				arcpy.AddMessage("+++++++++\n")
    				sys.exit(3)            
    			else:
    				arcpy.AddReturnMessage(i)
    				arcpy.AddMessage("+++++++++\n")
    
    		print("Creating database user...\n")
    		arcpy.CreateDatabaseUser_management(input_workspace=Connection_File_Name_full_path, user_authentication_type=user_type, user_name=dbuser, user_password=dbuser_pwd, role=role, tablespace_name=tablespace)
    		for i in range(arcpy.GetMessageCount()):
    			arcpy.AddReturnMessage(i)
    		arcpy.AddMessage("+++++++++\n")
    	except:
    		for i in range(arcpy.GetMessageCount()):
    			arcpy.AddReturnMessage(i)
    			
    #Check if no value entered for option	
    except SystemExit as e:
    	if e.code == 2:
    		parser.usage = ""
    		print("\n")
    		parser.print_help()   
    		parser.exit(2)

    您可以在安装了 ArcGIS Desktop(Standard 或 Advanced)、ArcGIS Server(Standard 或 Advanced)或具有 Geodatabase Update 扩展模块的 ArcGIS Engine 的计算机上运行脚本。

  2. .py 扩展名保存该文件。
  3. 运行脚本,同时提供特定于 PostgreSQL 数据库群集的选项和信息和想要创建的登录角色。

    在以下示例中,通过 Microsoft Windows 服务器运行的脚本名称为 create_database_user.py。经数据库身份验证的登录角色(地理数据)在 PostgreSQL 数据库集群 pgdb7 中创建,而相应的方案在数据库 gisdata 中创建。未将此用户添加到组角色。

    create_database_user.py --DBMS POSTGRESQL -i pgdb7 -D gisdata -U postgres -P $hHhH --utype DATABASE_USER -u geodata -p 0wn1t

    这是在 Linux 计算机上运行脚本的示例:

    ./create_database_user.py --DBMS POSTGRESQL -i pgdb7 -D gisdata -U postgres -P $hHhH --utype DATABASE_USER -u geodata -p 0wn1t

    提示:

    在命令提示符处输入 -h--help 以获取语法帮助。

此时,数据库已具有可创建表的用户。

创建登录以查看和编辑数据

可使用 SQL 为不创建数据的用户创建登录角色。如果您在 PostgreSQL 中为地理数据库执行了此操作,请确保公共组或指定用户具有创建临时表的权限。

也可创建登录组以简化向这些用户授予单个数据集权限的操作。

创建角色

以下步骤介绍如何使用 psql 创建组角色从而简化数据权限管理,以及创建属于该组角色的登录角色。

  1. 以具有在数据库集群中创建其他角色的权限的用户身份登录 psql。可以通过超级用户身份或被授予 createrole 权限的用户身份进行登录。
  2. 首先,使用 create role 命令创建两个登录组:一个用于可编辑数据集的用户(编辑人员),一个用于只能查看数据的用户(查看人员)。

    CREATE ROLE editors 
    NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT;
    CREATE ROLE viewers
    NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT;

  3. 接下来,创建属于编辑人员组的成员的登录角色。

    在本例中,将创建一个登录角色 (editor1),它设有加密密码。该角色不具有超级用户身份,无法创建数据库,且无法在数据库集群中创建角色。但是该角色属于组角色编辑人员的一员,并且将从组角色继承权限。

    CREATE ROLE editor1 LOGIN 
    ENCRYPTED PASSWORD 'sooper.secret' 
    NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT IN ROLE editors;
    更改登录角色名称并再次运行语句以便创建可在地理数据库中编辑数据的其他登录角色。

  4. 现在,创建属于查看人员组的成员的登录角色。

    在本例中,将创建一个登录角色 (reader1),它设有加密密码。该角色不具有超级用户身份,无法创建数据库,且无法在数据库集群中创建角色。但是该角色属于组角色查看人员的一员,并且将从组角色继承权限。

    CREATE ROLE reader1 LOGIN 
    ENCRYPTED PASSWORD 'almostas.secret' 
    NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT IN ROLE viewers;
    更改登录角色名称并再次运行语句以便创建只可在地理数据库中查看数据的其他登录角色。

  5. 为各个登录组授予 geodata 方案的 usage 权限。

    usage 权限允许编辑人员和查看人员的成员访问地理数据方案中的数据。如果不具有此权限,则地理数据无法向查看人员和编辑人员组角色的成员授予单个数据集的权限。

    GRANT USAGE ON SCHEMA geodata TO editors;
    GRANT USAGE ON SCHEMA geodata TO viewers;
  6. 如果要为地理数据库创建这些登录角色,且您已经更改了 sde 方案权限以便公众对其不具有 usage 权限,则请向编辑人员和查看人员组授予 sde 方案的 usage 权限。
    GRANT USAGE ON SCHEMA sde TO editors;
    GRANT USAGE ON SCHEMA sde TO viewers;

现在,您的数据库将会具有一个或多个要编辑数据的用户,以及一个或多个要查看数据的用户。

如果数据库或地理数据库中已存在数据集,则所有者可向查看人员组授予数据集的 select 权限,并向编辑人员组授予数据集的 selectinsertupdatedelete 权限。有关说明,请参阅授予和撤消数据集权限