第05章-安全配置与认证
第五章:安全配置与认证
5.1 引言
安全性是任何生产级应用的关键考虑因素,对于提供地理空间数据服务的 GeoServer Cloud 尤其重要。本章将全面介绍 GeoServer Cloud 的安全架构、认证机制和授权配置,帮助您构建安全可靠的地理空间服务平台。
GeoServer Cloud 继承了 GeoServer 强大的安全子系统,同时针对云原生部署环境进行了增强。我们将从基础的用户认证开始,逐步深入到企业级的 LDAP 集成、OAuth2 认证以及基于 ACL 的细粒度访问控制。
5.2 安全架构概述
5.2.1 安全组件层次
GeoServer Cloud 的安全架构分为多个层次:
┌─────────────────────────────────────────────────────────────────┐
│ 客户端请求 │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Gateway (API 网关) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 可选:集中式认证 / 速率限制 / WAF │ │
│ └─────────────────────────────────────────────────────────┘ │
└──────────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ GeoServer 安全过滤器链 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 认证过滤器 → 会话管理 → 授权决策 → 资源访问 │ │
│ └─────────────────────────────────────────────────────────┘ │
└──────────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────┼──────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 用户/角色存储 │ │ 服务访问规则 │ │ 数据访问规则 │
│ (XML/JDBC/ │ │ (WMS/WFS/ │ │ (图层/属性 │
│ LDAP) │ │ REST) │ │ 级别) │
└───────────────┘ └───────────────┘ └───────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ GeoServer ACL (可选) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 高级访问控制列表 - 基于规则的细粒度授权 │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
5.2.2 认证方式
GeoServer Cloud 支持多种认证方式:
| 认证方式 | 说明 | 适用场景 |
|---|---|---|
| HTTP Basic | 基本用户名/密码认证 | 开发测试、内部API |
| Form 登录 | Web 表单登录 | WebUI 管理界面 |
| API Key | 基于 Key 的认证 | 应用程序集成 |
| LDAP | 目录服务认证 | 企业环境 |
| OAuth2/OIDC | 第三方身份提供商 | 单点登录 |
| 匿名访问 | 无需认证 | 公开数据服务 |
5.2.3 授权模型
GeoServer 使用基于角色的访问控制(RBAC):
用户 (User)
│
└── 拥有多个 ──▶ 角色 (Role)
│
└── 授予 ──▶ 权限 (Permission)
│
├── 服务级别(WMS、WFS、REST)
├── 图层级别
├── 属性级别(字段)
└── 空间范围(区域)
5.3 基础认证配置
5.3.1 默认安全配置
GeoServer Cloud 默认配置:
- 管理员账户:admin / geoserver
- 匿名用户可访问 OWS 服务(只读)
- REST API 和 WebUI 需要认证
5.3.2 通过环境变量配置管理员
最简单的管理员配置方式:
services:
wms:
environment:
- GEOSERVER_ADMIN_USERNAME=admin
- GEOSERVER_ADMIN_PASSWORD=${ADMIN_PASSWORD}
这种方式的特点:
- 在所有配置之前生效
- 覆盖任何其他管理员配置
- 如果使用非默认用户名,原 admin 用户会被禁用
5.3.3 用户管理(XML 存储)
默认情况下,用户存储在 XML 文件中。通过 WebUI 管理:
- 登录 GeoServer WebUI
- 导航到 安全 → 用户、组和角色
- 选择"用户"标签页
创建新用户
用户名: analyst
密码: ******
启用: ✓
角色: ROLE_AUTHENTICATED, DATA_ANALYST
用户属性存储位置
<!-- security/usergroup/default/users.xml -->
<userRegistry>
<users>
<user name="admin" password="digest1:..." enabled="true"/>
<user name="analyst" password="digest1:..." enabled="true"/>
</users>
<groups/>
</userRegistry>
5.3.4 角色管理
内置角色
| 角色 | 说明 |
|---|---|
| ROLE_ADMINISTRATOR | 系统管理员,完全访问权限 |
| ROLE_AUTHENTICATED | 已认证用户 |
| ROLE_ANONYMOUS | 匿名用户 |
创建自定义角色
通过 WebUI 或 REST API:
curl -u admin:geoserver -X POST \
-H "Content-Type: application/json" \
-d '{"role":{"id":"DATA_ANALYST"}}' \
"http://localhost:9090/geoserver/cloud/rest/security/roles/role/DATA_ANALYST"
5.3.5 服务访问规则
配置服务级别的访问控制:
# security/services.properties
# 格式:服务.操作=角色列表
# WMS 服务
wms.GetCapabilities=*
wms.GetMap=*
wms.GetFeatureInfo=ROLE_AUTHENTICATED
# WFS 服务
wfs.GetCapabilities=*
wfs.GetFeature=ROLE_AUTHENTICATED
wfs.Transaction=ROLE_EDITOR
# REST API
rest.GET=ROLE_AUTHENTICATED
rest.POST=ROLE_ADMINISTRATOR
rest.PUT=ROLE_ADMINISTRATOR
rest.DELETE=ROLE_ADMINISTRATOR
5.3.6 图层访问规则
配置图层级别的访问控制:
# security/layers.properties
# 格式:工作区.图层.权限=角色列表
# 全局默认规则
*.*.r=*
*.*.w=ROLE_AUTHENTICATED
# 特定图层规则
sensitive.classified.r=ROLE_CLASSIFIED_READ
sensitive.classified.w=ROLE_CLASSIFIED_WRITE
# 隐藏图层
secret.*.r=ROLE_SECRET_ACCESS
5.4 JDBC 安全存储
5.4.1 概述
JDBC 安全扩展允许将用户、组和角色存储在关系数据库中,适用于:
- 大量用户管理
- 与现有用户数据库集成
- 需要程序化用户管理
5.4.2 配置 JDBC 安全
1. 创建数据库表
-- 用户表
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(128) NOT NULL UNIQUE,
password VARCHAR(256) NOT NULL,
enabled BOOLEAN DEFAULT TRUE
);
-- 角色表
CREATE TABLE roles (
id SERIAL PRIMARY KEY,
rolename VARCHAR(64) NOT NULL UNIQUE
);
-- 用户角色关联表
CREATE TABLE user_roles (
user_id INTEGER REFERENCES users(id),
role_id INTEGER REFERENCES roles(id),
PRIMARY KEY (user_id, role_id)
);
-- 组表
CREATE TABLE groups (
id SERIAL PRIMARY KEY,
groupname VARCHAR(128) NOT NULL UNIQUE,
enabled BOOLEAN DEFAULT TRUE
);
-- 用户组关联表
CREATE TABLE user_groups (
user_id INTEGER REFERENCES users(id),
group_id INTEGER REFERENCES groups(id),
PRIMARY KEY (user_id, group_id)
);
-- 组角色关联表
CREATE TABLE group_roles (
group_id INTEGER REFERENCES groups(id),
role_id INTEGER REFERENCES roles(id),
PRIMARY KEY (group_id, role_id)
);
2. 配置 JNDI 数据源
jndi:
datasources:
usersdb:
enabled: true
url: jdbc:postgresql://localhost:5432/users
username: geoserver
password: ${USERS_DB_PASSWORD}
3. 配置 JDBC 用户组服务
通过 WebUI 配置:
- 安全 → 用户、组和角色
- 添加新的用户组服务
- 选择 JDBC 类型
- 配置数据源和 SQL 查询
5.4.3 自定义 SQL 查询
# 用户查询
users-by-username-sql: >
SELECT username, password, enabled
FROM users WHERE username = ?
# 角色查询
roles-by-username-sql: >
SELECT r.rolename
FROM roles r
JOIN user_roles ur ON r.id = ur.role_id
JOIN users u ON ur.user_id = u.id
WHERE u.username = ?
# 组角色查询
roles-by-group-sql: >
SELECT r.rolename
FROM roles r
JOIN group_roles gr ON r.id = gr.role_id
JOIN groups g ON gr.group_id = g.id
WHERE g.groupname = ?
5.5 LDAP 认证集成
5.5.1 概述
LDAP(轻量级目录访问协议)集成允许使用企业目录服务进行认证,常见的 LDAP 服务器:
- Microsoft Active Directory
- OpenLDAP
- Apache Directory Server
- 389 Directory Server
5.5.2 基本 LDAP 配置
1. 配置 LDAP 认证提供者
通过 WebUI:安全 → 认证 → 添加新的认证提供者
# LDAP 服务器配置
ldap:
server:
url: ldap://ldap.example.com:389
base-dn: dc=example,dc=com
# 绑定凭据(用于搜索用户)
bind:
dn: cn=geoserver,ou=services,dc=example,dc=com
password: ${LDAP_BIND_PASSWORD}
# 用户搜索
user:
search-base: ou=users
search-filter: (uid={0})
# 组搜索
group:
search-base: ou=groups
search-filter: (member={0})
role-attribute: cn
2. Active Directory 特定配置
ldap:
server:
url: ldap://ad.example.com:389
base-dn: dc=example,dc=com
bind:
dn: CN=GeoServer Service,OU=Services,DC=example,DC=com
password: ${AD_BIND_PASSWORD}
user:
search-base: OU=Users
search-filter: (sAMAccountName={0})
group:
search-base: OU=Groups
search-filter: (member={0})
role-attribute: cn
5.5.3 LDAP 角色映射
将 LDAP 组映射到 GeoServer 角色:
# LDAP 组 → GeoServer 角色映射
LDAP Group: cn=GIS_Admins,ou=groups,dc=example,dc=com
GeoServer Role: ROLE_ADMINISTRATOR
LDAP Group: cn=GIS_Editors,ou=groups,dc=example,dc=com
GeoServer Role: ROLE_EDITOR
LDAP Group: cn=GIS_Viewers,ou=groups,dc=example,dc=com
GeoServer Role: ROLE_AUTHENTICATED
5.5.4 LDAPS 安全连接
使用 SSL/TLS 保护 LDAP 连接:
ldap:
server:
url: ldaps://ldap.example.com:636
# 或使用 StartTLS
# url: ldap://ldap.example.com:389
# use-start-tls: true
ssl:
# 信任存储配置
trust-store: /etc/ssl/ldap-truststore.jks
trust-store-password: ${LDAP_TRUSTSTORE_PASSWORD}
5.6 OAuth2 / OpenID Connect
5.6.1 概述
OAuth2 和 OpenID Connect (OIDC) 支持与第三方身份提供商集成,实现单点登录(SSO):
- GitHub
- Azure AD
- Keycloak
- Okta
- Auth0
5.6.2 配置 OAuth2
使用 geOrchestra Gateway
GeoServer Cloud 推荐使用 geOrchestra Gateway 实现 OAuth2 认证:
services:
gateway:
image: georchestra/gateway:latest
environment:
- SPRING_PROFILES_ACTIVE=oauth2
- OAUTH2_CLIENT_ID=${OAUTH2_CLIENT_ID}
- OAUTH2_CLIENT_SECRET=${OAUTH2_CLIENT_SECRET}
- OAUTH2_AUTHORIZATION_URI=https://auth.example.com/authorize
- OAUTH2_TOKEN_URI=https://auth.example.com/token
- OAUTH2_USER_INFO_URI=https://auth.example.com/userinfo
5.6.3 Keycloak 集成示例
1. Keycloak 配置
在 Keycloak 中创建客户端:
- Client ID: geoserver-cloud
- Client Protocol: openid-connect
- Access Type: confidential
- Valid Redirect URIs: http://localhost:9090/*
2. GeoServer Cloud 配置
spring:
security:
oauth2:
client:
registration:
keycloak:
client-id: geoserver-cloud
client-secret: ${KEYCLOAK_CLIENT_SECRET}
scope: openid,profile,email,roles
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
provider:
keycloak:
issuer-uri: https://keycloak.example.com/realms/geoserver
user-name-attribute: preferred_username
5.6.4 角色映射
从 OAuth2 令牌中提取角色:
geoserver:
security:
oauth2:
role-mapping:
enabled: true
# JWT claim 路径
claim-path: realm_access.roles
# 角色前缀
role-prefix: ROLE_
# 角色名称映射
mappings:
gis-admin: ADMINISTRATOR
gis-editor: EDITOR
gis-user: AUTHENTICATED
5.7 GeoServer ACL 访问控制
5.7.1 概述
GeoServer ACL 是一个高级授权系统,提供比默认安全子系统更细粒度的访问控制:
- 基于规则的访问控制
- 空间范围限制
- 属性过滤
- 请求限制
5.7.2 部署 GeoServer ACL
添加 ACL 服务到部署
services:
acl:
image: geoservercloud/geoserver-acl:${TAG}
environment:
- SPRING_PROFILES_ACTIVE=pgconfig
- PGCONFIG_HOST=database
- PGCONFIG_DATABASE=geoserver_acl
depends_on:
- database
wms:
environment:
- SPRING_PROFILES_ACTIVE=pgconfig,acl
- GEOSERVER_ACL_ENABLED=true
- GEOSERVER_ACL_URL=http://acl:8080
5.7.3 ACL 规则配置
规则结构
{
"priority": 1,
"access": "ALLOW",
"role": "ROLE_ANALYST",
"service": "WFS",
"request": "GetFeature",
"workspace": "analytics",
"layer": "sales_data",
"attributes": {
"include": ["id", "region", "amount"],
"exclude": ["customer_ssn"]
},
"spatialFilter": {
"type": "INTERSECTS",
"geometry": {
"type": "Polygon",
"coordinates": [[[...], ...]]
}
}
}
通过 REST API 管理规则
# 创建规则
curl -u admin:geoserver -X POST \
-H "Content-Type: application/json" \
-d '{
"priority": 10,
"access": "ALLOW",
"role": "ROLE_DATA_VIEWER",
"service": "WMS",
"workspace": "*",
"layer": "*"
}' \
"http://localhost:8080/acl/api/rules"
# 列出所有规则
curl -u admin:geoserver \
"http://localhost:8080/acl/api/rules"
5.7.4 空间访问限制
限制用户只能访问特定地理范围的数据:
{
"priority": 5,
"access": "LIMIT",
"role": "ROLE_REGION_NORTH",
"service": "*",
"layer": "all_regions",
"spatialFilter": {
"type": "INTERSECTS",
"crs": "EPSG:4326",
"geometry": {
"type": "Polygon",
"coordinates": [[
[-180, 45], [180, 45], [180, 90], [-180, 90], [-180, 45]
]]
}
}
}
5.7.5 属性级别访问控制
限制用户可以访问的字段:
{
"priority": 8,
"access": "ALLOW",
"role": "ROLE_PUBLIC_USER",
"service": "WFS",
"layer": "parcels",
"attributes": {
"include": ["id", "address", "area"],
"exclude": ["owner_name", "tax_value", "ssn"]
}
}
5.8 API Key 认证
5.8.1 配置 API Key 认证
启用 Key Authentication 扩展:
geoserver:
security:
auth-key:
enabled: true
# 认证提供者类型
provider: property-file # 或 user-property, web-service
# 请求参数名
parameter-name: apikey
# 请求头名
header-name: X-API-Key
5.8.2 API Key 存储方式
属性文件方式
# security/authkey/keys.properties
# 格式:apikey=username
abc123def456=user1
xyz789uvw012=user2
用户属性方式
每个用户可以有自己的 API Key,存储在用户属性中:
<user name="user1" password="...">
<property name="apikey" value="abc123def456"/>
</user>
5.8.3 使用 API Key
# 通过查询参数
curl "http://localhost:9090/geoserver/cloud/wms?apikey=abc123def456&service=WMS&request=GetCapabilities"
# 通过请求头
curl -H "X-API-Key: abc123def456" \
"http://localhost:9090/geoserver/cloud/wms?service=WMS&request=GetCapabilities"
5.9 安全最佳实践
5.9.1 密码策略
配置强密码策略:
geoserver:
security:
password:
# 最小长度
min-length: 12
# 必须包含
require-uppercase: true
require-lowercase: true
require-digit: true
require-special: true
# 密码过期
max-age-days: 90
# 禁止重复使用
history-count: 5
5.9.2 会话管理
server:
servlet:
session:
timeout: 30m # 会话超时
cookie:
secure: true # 仅 HTTPS
http-only: true # 防止 XSS
same-site: strict # CSRF 保护
5.9.3 HTTPS 配置
生产环境必须使用 HTTPS:
在 Gateway 配置 SSL
server:
ssl:
enabled: true
key-store: /etc/ssl/keystore.p12
key-store-password: ${SSL_KEYSTORE_PASSWORD}
key-store-type: PKCS12
key-alias: gateway
或使用反向代理(推荐)
# Nginx 配置
server {
listen 443 ssl http2;
server_name geoserver.example.com;
ssl_certificate /etc/ssl/certs/geoserver.crt;
ssl_certificate_key /etc/ssl/private/geoserver.key;
location / {
proxy_pass http://gateway:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
5.9.4 请求限制
在 Gateway 配置请求速率限制:
spring:
cloud:
gateway:
filter:
request-rate-limiter:
enabled: true
routes:
- id: wms
uri: lb://wms-service
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 100
redis-rate-limiter.burstCapacity: 200
key-resolver: "#{@userKeyResolver}"
5.9.5 审计日志
启用安全审计日志:
logging:
level:
org.geoserver.security: INFO
org.springframework.security: INFO
geoserver:
security:
audit:
enabled: true
log-successful: true
log-failed: true
5.10 故障排除
5.10.1 常见安全问题
问题:认证失败
# 检查用户是否存在
curl -u admin:geoserver \
"http://localhost:9090/geoserver/cloud/rest/security/usergroup/users.json"
# 检查认证过滤器链
curl -u admin:geoserver \
"http://localhost:9090/geoserver/cloud/rest/security/auth/chains.json"
问题:授权被拒绝
# 检查用户角色
curl -u admin:geoserver \
"http://localhost:9090/geoserver/cloud/rest/security/roles/user/analyst.json"
# 检查访问规则
cat security/layers.properties
cat security/services.properties
5.10.2 LDAP 连接问题
# 测试 LDAP 连接
ldapsearch -x -H ldap://ldap.example.com:389 \
-D "cn=geoserver,ou=services,dc=example,dc=com" \
-W -b "dc=example,dc=com" "(uid=testuser)"
# 检查证书(LDAPS)
openssl s_client -connect ldap.example.com:636
5.11 本章小结
本章全面介绍了 GeoServer Cloud 的安全配置:
-
安全架构:了解了多层安全架构和认证授权模型。
-
基础认证:配置了用户、角色和访问规则。
-
JDBC 存储:将安全数据存储在关系数据库中。
-
LDAP 集成:与企业目录服务集成。
-
OAuth2/OIDC:实现单点登录。
-
GeoServer ACL:配置细粒度的访问控制。
-
API Key:为应用程序提供简化的认证方式。
-
最佳实践:密码策略、会话管理、HTTPS 配置等。
在下一章中,我们将学习如何使用 Docker Compose 进行生产级部署。
5.12 思考题
-
在什么场景下应该使用 LDAP 认证而不是本地用户存储?
-
GeoServer ACL 与默认的访问规则有什么区别?什么时候需要使用 ACL?
-
如何设计一个支持多租户的安全方案,确保租户间的数据隔离?
-
OAuth2 的 authorization_code 流程与 client_credentials 流程有什么区别?各适用于什么场景?
-
在高安全要求的环境中,应该采取哪些额外的安全措施?

浙公网安备 33010602011771号