14. 身份验证基础设施

提示

如果您在pyqgis控制台之外,则此页面上的代码片段需要以下导入:

 1from qgis.core import (
 2  QgsApplication,
 3  QgsRasterLayer,
 4  QgsAuthMethodConfig,
 5  QgsDataSourceUri,
 6  QgsPkiBundle,
 7  QgsMessageLog,
 8)
 9
10from qgis.gui import (
11    QgsAuthAuthoritiesEditor,
12    QgsAuthConfigEditor,
13    QgsAuthConfigSelect,
14    QgsAuthSettingsWidget,
15)
16
17from qgis.PyQt.QtWidgets import (
18    QWidget,
19    QTabWidget,
20)
21
22from qgis.PyQt.QtNetwork import QSslCertificate

14.1. 引言

有关身份验证基础架构的用户参考,请参阅《用户手册》中 身份验证系统概述 段落。

本章从开发人员的角度介绍使用身份验证系统的最佳做法。

每当需要凭据才能访问特定资源时,例如,当层建立到Postgres数据库的连接时,数据提供商在QGIS Desktop中广泛使用身份验证系统。

QGISGui库中还有几个小部件,插件开发人员可以使用它们轻松地将身份验证基础设施集成到他们的代码中:

可以从身份验证基础结构中读取良好的代码引用 tests code

警告

由于在身份验证基础设施设计期间考虑到的安全约束,只有选定的内部方法子集向Python公开。

14.2. 词汇表

以下是本章中讨论的最常见对象的一些定义。

主密码

允许访问和解密存储在QGIS身份验证数据库中的凭据的密码

身份验证数据库

A Master Password 加密Sqlite数据库 qgis-auth.db 哪里 Authentication Configuration 都被储存起来。例如用户/密码、个人证书和密钥、证书颁发机构

身份验证数据库

Authentication Database

身份验证配置

一组身份验证数据 Authentication Method 。例如,基本身份验证方法存储用户/密码的组合。

身份验证配置

Authentication Configuration

身份验证方法

用于进行身份验证的特定方法。每种方法都有自己的协议用于获得身份验证级别。每个方法都被实现为在QGIS身份验证基础设施初始化期间动态加载的共享库。

14.3. QgsAuthManager入口点

这个 QgsAuthManager Singleton是使用存储在QGIS加密中的凭据的入口点 Authentication DB ,即 qgis-auth.db 活动目录下的文件 user profile 文件夹。

这个类负责用户交互:通过请求设置主密码或通过透明地使用它来访问加密的存储信息。

14.3.1. 初始化管理器并设置主密码

下面的片断给出了设置主密码以打开对身份验证设置的访问权限的示例。代码注释对于理解代码段很重要。

 1authMgr = QgsApplication.authManager()
 2
 3# check if QgsAuthManager has already been initialized... a side effect
 4# of the QgsAuthManager.init() is that AuthDbPath is set.
 5# QgsAuthManager.init() is executed during QGIS application init and hence
 6# you do not normally need to call it directly.
 7if authMgr.authenticationDatabasePath():
 8    # already initialized => we are inside a QGIS app.
 9    if authMgr.masterPasswordIsSet():
10        msg = 'Authentication master password not recognized'
11        assert authMgr.masterPasswordSame("your master password"), msg
12    else:
13        msg = 'Master password could not be set'
14        # The verify parameter checks if the hash of the password was
15        # already saved in the authentication db
16        assert authMgr.setMasterPassword("your master password",
17                                          verify=True), msg
18else:
19    # outside qgis, e.g. in a testing environment => setup env var before
20    # db init
21    os.environ['QGIS_AUTH_DB_DIR_PATH'] = "/path/where/located/qgis-auth.db"
22    msg = 'Master password could not be set'
23    assert authMgr.setMasterPassword("your master password", True), msg
24    authMgr.init("/path/where/located/qgis-auth.db")

14.3.2. 使用新的身份验证配置条目填充身份验证数据库

任何存储的凭据都是 Authentication Configuration 对象的实例 QgsAuthMethodConfig 使用如下所示的唯一字符串访问的类:

authcfg = 'fm1s770'

该字符串是在使用QGISAPI或图形用户界面创建条目时自动生成的,但如果必须在组织内的多个用户之间共享配置(使用不同的凭据),则手动将其设置为已知值可能很有用。

QgsAuthMethodConfig 是任何 Authentication Method 。任何身份验证方法都会设置将存储身份验证信息的配置散列映射。下面是一个有用的片段,用于存储假定的Alice用户的PKI路径凭据:

 1authMgr = QgsApplication.authManager()
 2# set alice PKI data
 3config = QgsAuthMethodConfig()
 4config.setName("alice")
 5config.setMethod("PKI-Paths")
 6config.setUri("https://example.com")
 7config.setConfig("certpath", "path/to/alice-cert.pem" )
 8config.setConfig("keypath", "path/to/alice-key.pem" )
 9# check if method parameters are correctly set
10assert config.isValid()
11
12# register alice data in authdb returning the ``authcfg`` of the stored
13# configuration
14authMgr.storeAuthenticationConfig(config)
15newAuthCfgId = config.id()
16assert newAuthCfgId

14.3.2.1. 可用的身份验证方法

Authentication Method 库在身份验证管理器初始化期间动态加载。可用的身份验证方法包括:

  1. Basic 用户和密码身份验证

  2. Esri-Token 基于ESRI令牌的身份验证

  3. Identity-Cert 身份证书认证

  4. OAuth2 OAuth2身份验证

  5. PKI-Paths PKI路径身份验证

  6. PKI-PKCS#12 PKI PKCS#12身份验证

14.3.2.2. 派驻权威人士

1authMgr = QgsApplication.authManager()
2# add authorities
3cacerts = QSslCertificate.fromPath( "/path/to/ca_chains.pem" )
4assert cacerts is not None
5# store CA
6authMgr.storeCertAuthorities(cacerts)
7# and rebuild CA caches
8authMgr.rebuildCaCertsCache()
9authMgr.rebuildTrustedCaCertsCache()

14.3.2.3. 使用QgsPkiBundle管理PKI捆绑包

打包在SslCert、SslKey和CA链上组成的PKI包的一个方便类是 QgsPkiBundle 班级。以下是获得密码保护的代码片段:

1# add alice cert in case of key with pwd
2caBundlesList = []  # List of CA bundles
3bundle = QgsPkiBundle.fromPemPaths( "/path/to/alice-cert.pem",
4                                     "/path/to/alice-key_w-pass.pem",
5                                     "unlock_pwd",
6                                     caBundlesList )
7assert bundle is not None
8# You can check bundle validity by calling:
9# bundle.isValid()

参考 QgsPkiBundle 用于从捆绑包中提取证书/密钥/CA的类文档。

14.3.3. 从身份验证数据库中删除条目

我们可以从以下位置删除条目 Authentication Database 使用它的 authcfg 具有以下代码片断的标识符:

authMgr = QgsApplication.authManager()
authMgr.removeAuthenticationConfig( "authCfg_Id_to_remove" )

14.3.4. 将Authcfg扩展留给QgsAuthManager

最好的方法是使用 Authentication Config 存储在 Authentication DB 正在使用唯一标识符来引用它 authcfg 。扩展,意味着将其从一个标识符转换为一套完整的凭据。使用存储的最佳实践 Authentication Config S,让它由身份验证管理器自动管理。存储配置的常见用途是连接到启用身份验证的服务,如WMS或WFS或数据库连接。

备注

考虑到并不是所有的QGIS数据提供程序都集成了身份验证基础设施。从基类派生的每个身份验证方法 QgsAuthMethod 并支持一组不同的提供商。例如, certIdentity() 方法支持以下提供程序列表:

authM = QgsApplication.authManager()
print(authM.authMethod("Identity-Cert").supportedDataProviders())

示例输出:

['ows', 'wfs', 'wcs', 'wms', 'postgres']

例如,要使用以标识的存储凭据访问WMS服务 authcfg = 'fm1s770' ,我们只需使用 authcfg 在数据源URL中,如以下代码片断所示:

 1authCfg = 'fm1s770'
 2quri = QgsDataSourceUri()
 3quri.setParam("layers", 'usa:states')
 4quri.setParam("styles", '')
 5quri.setParam("format", 'image/png')
 6quri.setParam("crs", 'EPSG:4326')
 7quri.setParam("dpiMode", '7')
 8quri.setParam("featureCount", '10')
 9quri.setParam("authcfg", authCfg)   # <---- here my authCfg url parameter
10quri.setParam("contextualWMSLegend", '0')
11quri.setParam("url", 'https://my_auth_enabled_server_ip/wms')
12rlayer = QgsRasterLayer(str(quri.encodedUri(), "utf-8"), 'states', 'wms')

在大写字母中, wms 提供商将注意扩展 authcfg 就在设置HTTP连接之前,使用凭据设置URI参数。

警告

开发商将不得不离开 authcfg 扩展到 QgsAuthManager 通过这种方式,他将确保扩张不会做得太早。

通常是URI字符串,使用 QgsDataSourceURI 类用于按以下方式设置数据源:

authCfg = 'fm1s770'
quri = QgsDataSourceUri("my WMS uri here")
quri.setParam("authcfg", authCfg)
rlayer = QgsRasterLayer( quri.uri(False), 'states', 'wms')

备注

这个 False 参数对于避免URI完全扩展 authcfg URI中存在的ID。

14.3.4.1. 其他数据提供程序的PKI示例

其他示例可以直接在上游的QGIS测试中读取,如下所示 test_authmanager_pki_owstest_authmanager_pki_postgres

14.4. 调整插件以使用身份验证基础架构

许多第三方插件都在使用HTTPLIb2或其他Python网络库来管理HTTP连接,而不是与 QgsNetworkAccessManager 及其相关的身份验证基础架构集成。

为了便于此集成,创建了一个名为 NetworkAccessManager 。它的代码可以在 here

此帮助器类可以在以下代码片断中使用:

1http = NetworkAccessManager(authid="my_authCfg", exception_class=My_FailedRequestError)
2try:
3  response, content = http.request( "my_rest_url" )
4except My_FailedRequestError, e:
5  # Handle exception
6  pass

14.5. 身份验证图形用户界面

在这一段中,列出了可用于在定制接口中集成身份验证基础设施的可用图形用户界面。

14.5.1. 选择凭据的图形用户界面

如果有必要选择一个 Authentication Configuration 从存储在 Authentication DB 它在图形用户界面类中可用 QgsAuthConfigSelect

../../_images/QgsAuthConfigSelect.png

并且可以在以下代码片断中使用:

1# create the instance of the QgsAuthConfigSelect GUI hierarchically linked to
2# the widget referred with `parent`
3parent = QWidget()  # Your GUI parent widget
4gui = QgsAuthConfigSelect( parent, "postgres" )
5# add the above created gui in a new tab of the interface where the
6# GUI has to be integrated
7tabGui = QTabWidget()
8tabGui.insertTab( 1, gui, "Configurations" )

上面的示例取自QGIS源代码 code 。图形用户界面构造函数的第二个参数引用数据提供程序类型。该参数用于限制兼容的 Authentication Method S与指定的提供程序。

14.5.2. 身份验证编辑器图形用户界面

用于管理凭据、授权和访问身份验证实用程序的完整图形用户界面由管理 QgsAuthEditorWidgets 班级。

../../_images/QgsAuthEditorWidgets.png

并且可以在以下代码片断中使用:

1# create the instance of the QgsAuthEditorWidgets GUI hierarchically linked to
2# the widget referred with `parent`
3parent = QWidget()  # Your GUI parent widget
4gui = QgsAuthConfigSelect( parent )
5gui.show()

可以在相关的 test

14.5.3. 权限编辑器图形用户界面

仅用于管理权限的图形用户界面由 QgsAuthAuthoritiesEditor 班级。

../../_images/QgsAuthAuthoritiesEditor.png

并且可以在以下代码片断中使用:

1# create the instance of the QgsAuthAuthoritiesEditor GUI hierarchically
2#  linked to the widget referred with `parent`
3parent = QWidget()  # Your GUI parent widget
4gui = QgsAuthAuthoritiesEditor( parent )
5gui.show()