堡垒机:SSH代理与权限管理实战

1. 堡垒机概述

堡垒机是一种网络安全设备,用于管理和控制对内部网络资源的访问。本文将详细介绍堡垒机系统、SSH代理、权限管理、审计日志和安全管理的完整解决方案。

1.1 核心功能

  1. SSH代理: 安全的SSH连接代理和管理
  2. 权限管理: 细粒度的用户权限控制
  3. 审计日志: 完整的操作审计和日志记录
  4. 安全管理: 安全策略和访问控制
  5. 会话管理: 实时会话监控和管理

1.2 技术架构

1
2
3
4
5
用户 → 堡垒机 → SSH代理 → 目标服务器
↓ ↓ ↓ ↓
认证 → 权限检查 → 连接管理 → 命令执行
↓ ↓ ↓ ↓
审计 → 日志记录 → 会话监控 → 操作记录

2. 堡垒机配置

2.1 Maven依赖配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!-- pom.xml -->
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Spring Boot Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>

<!-- SSH客户端 -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>

<!-- WebSocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
</dependencies>

2.2 堡垒机配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/**
* 堡垒机配置类
*/
@Configuration
public class BastionHostConfig {

@Value("${bastion.host:localhost}")
private String bastionHost;

@Value("${bastion.port:22}")
private int bastionPort;

@Value("${bastion.max-sessions:100}")
private int maxSessions;

@Value("${bastion.session-timeout:3600}")
private int sessionTimeout;

/**
* 堡垒机配置属性
*/
@Bean
public BastionHostProperties bastionHostProperties() {
return BastionHostProperties.builder()
.bastionHost(bastionHost)
.bastionPort(bastionPort)
.maxSessions(maxSessions)
.sessionTimeout(sessionTimeout)
.build();
}

/**
* SSH连接管理器
*/
@Bean
public SSHConnectionManager sshConnectionManager() {
return new SSHConnectionManager(bastionHostProperties());
}

/**
* 权限管理器
*/
@Bean
public PermissionManager permissionManager() {
return new PermissionManager();
}

/**
* 审计日志服务
*/
@Bean
public AuditLogService auditLogService() {
return new AuditLogService();
}
}

/**
* 堡垒机配置属性
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BastionHostProperties {
private String bastionHost;
private int bastionPort;
private int maxSessions;
private int sessionTimeout;

// 安全配置
private boolean enableEncryption = true;
private String encryptionAlgorithm = "AES";
private int keySize = 256;

// 审计配置
private boolean enableAudit = true;
private String auditLogPath = "/var/log/bastion";
private int auditLogRetentionDays = 90;

// 会话配置
private boolean enableSessionRecording = true;
private String sessionRecordPath = "/var/records/bastion";
private int sessionRecordRetentionDays = 30;
}

3. 数据模型定义

3.1 堡垒机数据模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/**
* 用户模型
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BastionUser {
private Long id;
private String username;
private String password;
private String email;
private String phone;
private String role;
private boolean enabled;
private LocalDateTime createTime;
private LocalDateTime lastLoginTime;
private String lastLoginIp;
}

/**
* 目标服务器模型
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TargetServer {
private Long id;
private String name;
private String host;
private int port;
private String username;
private String password;
private String keyPath;
private String description;
private boolean enabled;
private LocalDateTime createTime;
}

/**
* 权限模型
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Permission {
private Long id;
private Long userId;
private Long serverId;
private String permissionType; // READ, WRITE, EXECUTE, ADMIN
private boolean enabled;
private LocalDateTime createTime;
private LocalDateTime expireTime;
}

/**
* SSH会话模型
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SSHSession {
private String sessionId;
private Long userId;
private Long serverId;
private String username;
private String host;
private int port;
private LocalDateTime startTime;
private LocalDateTime endTime;
private String status; // ACTIVE, CLOSED, TIMEOUT
private String clientIp;
private String clientPort;
}

/**
* 审计日志模型
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AuditLog {
private Long id;
private Long userId;
private String username;
private String action;
private String resource;
private String result;
private String details;
private String clientIp;
private LocalDateTime timestamp;
}

/**
* 命令执行记录
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CommandRecord {
private Long id;
private String sessionId;
private Long userId;
private String command;
private String output;
private String result;
private LocalDateTime timestamp;
}

4. SSH连接管理器

4.1 SSH连接管理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/**
* SSH连接管理器
*/
@Service
public class SSHConnectionManager {

private final BastionHostProperties properties;
private final Map<String, SSHSession> activeSessions = new ConcurrentHashMap<>();
private final Map<String, Session> jschSessions = new ConcurrentHashMap<>();

public SSHConnectionManager(BastionHostProperties properties) {
this.properties = properties;
}

/**
* 建立SSH连接
* @param userId 用户ID
* @param serverId 服务器ID
* @param targetServer 目标服务器
* @return SSH会话
*/
public SSHSession createSSHConnection(Long userId, Long serverId, TargetServer targetServer) {
try {
// 1. 检查会话数量限制
if (activeSessions.size() >= properties.getMaxSessions()) {
throw new BusinessException("已达到最大会话数限制");
}

// 2. 创建JSch会话
JSch jsch = new JSch();
Session session = jsch.getSession(targetServer.getUsername(), targetServer.getHost(), targetServer.getPort());

// 3. 设置认证方式
if (targetServer.getKeyPath() != null && !targetServer.getKeyPath().isEmpty()) {
jsch.addIdentity(targetServer.getKeyPath());
} else {
session.setPassword(targetServer.getPassword());
}

// 4. 设置连接参数
session.setConfig("StrictHostKeyChecking", "no");
session.setTimeout(30000);

// 5. 建立连接
session.connect();

// 6. 创建SSH会话
String sessionId = UUID.randomUUID().toString();
SSHSession sshSession = SSHSession.builder()
.sessionId(sessionId)
.userId(userId)
.serverId(serverId)
.username(targetServer.getUsername())
.host(targetServer.getHost())
.port(targetServer.getPort())
.startTime(LocalDateTime.now())
.status("ACTIVE")
.clientIp(getClientIp())
.build();

// 7. 保存会话
activeSessions.put(sessionId, sshSession);
jschSessions.put(sessionId, session);

log.info("SSH连接建立成功: sessionId={}, host={}:{}", sessionId, targetServer.getHost(), targetServer.getPort());

return sshSession;

} catch (Exception e) {
log.error("建立SSH连接失败: host={}:{}", targetServer.getHost(), targetServer.getPort(), e);
throw new BusinessException("建立SSH连接失败: " + e.getMessage());
}
}

/**
* 执行SSH命令
* @param sessionId 会话ID
* @param command 命令
* @return 命令执行结果
*/
public CommandResult executeCommand(String sessionId, String command) {
try {
// 1. 获取会话
SSHSession sshSession = activeSessions.get(sessionId);
if (sshSession == null) {
throw new BusinessException("会话不存在或已关闭");
}

Session session = jschSessions.get(sessionId);
if (session == null || !session.isConnected()) {
throw new BusinessException("SSH会话已断开");
}

// 2. 创建通道
ChannelExec channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);

// 3. 设置输入输出流
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
channel.setOutputStream(outputStream);
channel.setErrStream(errorStream);

// 4. 执行命令
channel.connect();

// 5. 等待执行完成
while (channel.isConnected()) {
Thread.sleep(100);
}

// 6. 获取结果
String output = outputStream.toString();
String error = errorStream.toString();
int exitStatus = channel.getExitStatus();

// 7. 关闭通道
channel.disconnect();

// 8. 记录命令执行
recordCommandExecution(sessionId, sshSession.getUserId(), command, output, error, exitStatus);

return CommandResult.builder()
.success(exitStatus == 0)
.output(output)
.error(error)
.exitStatus(exitStatus)
.timestamp(LocalDateTime.now())
.build();

} catch (Exception e) {
log.error("执行SSH命令失败: sessionId={}, command={}", sessionId, command, e);
throw new BusinessException("执行SSH命令失败: " + e.getMessage());
}
}

/**
* 关闭SSH连接
* @param sessionId 会话ID
*/
public void closeSSHConnection(String sessionId) {
try {
// 1. 获取会话
SSHSession sshSession = activeSessions.get(sessionId);
if (sshSession != null) {
sshSession.setEndTime(LocalDateTime.now());
sshSession.setStatus("CLOSED");
}

// 2. 关闭JSch会话
Session session = jschSessions.get(sessionId);
if (session != null && session.isConnected()) {
session.disconnect();
}

// 3. 清理会话
activeSessions.remove(sessionId);
jschSessions.remove(sessionId);

log.info("SSH连接关闭成功: sessionId={}", sessionId);

} catch (Exception e) {
log.error("关闭SSH连接失败: sessionId={}", sessionId, e);
}
}

/**
* 获取活跃会话列表
* @return 活跃会话列表
*/
public List<SSHSession> getActiveSessions() {
return new ArrayList<>(activeSessions.values());
}

/**
* 获取用户活跃会话
* @param userId 用户ID
* @return 用户活跃会话列表
*/
public List<SSHSession> getUserActiveSessions(Long userId) {
return activeSessions.values().stream()
.filter(session -> session.getUserId().equals(userId))
.collect(Collectors.toList());
}

/**
* 记录命令执行
* @param sessionId 会话ID
* @param userId 用户ID
* @param command 命令
* @param output 输出
* @param error 错误
* @param exitStatus 退出状态
*/
private void recordCommandExecution(String sessionId, Long userId, String command,
String output, String error, int exitStatus) {
try {
CommandRecord record = CommandRecord.builder()
.sessionId(sessionId)
.userId(userId)
.command(command)
.output(output)
.result(exitStatus == 0 ? "SUCCESS" : "FAILED")
.timestamp(LocalDateTime.now())
.build();

// 保存命令记录
saveCommandRecord(record);

} catch (Exception e) {
log.error("记录命令执行失败", e);
}
}

/**
* 保存命令记录
* @param record 命令记录
*/
private void saveCommandRecord(CommandRecord record) {
// 实现命令记录保存逻辑
log.info("命令执行记录: sessionId={}, command={}, result={}",
record.getSessionId(), record.getCommand(), record.getResult());
}

/**
* 获取客户端IP
* @return 客户端IP
*/
private String getClientIp() {
// 实现获取客户端IP的逻辑
return "127.0.0.1";
}
}

/**
* 命令执行结果
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CommandResult {
private boolean success;
private String output;
private String error;
private int exitStatus;
private LocalDateTime timestamp;
}

5. 权限管理器

5.1 权限管理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/**
* 权限管理器
*/
@Service
public class PermissionManager {

private final Map<Long, Set<Permission>> userPermissions = new ConcurrentHashMap<>();
private final Map<Long, Set<Permission>> serverPermissions = new ConcurrentHashMap<>();

/**
* 检查用户权限
* @param userId 用户ID
* @param serverId 服务器ID
* @param permissionType 权限类型
* @return 是否有权限
*/
public boolean checkPermission(Long userId, Long serverId, String permissionType) {
try {
// 1. 获取用户权限
Set<Permission> permissions = userPermissions.get(userId);
if (permissions == null) {
return false;
}

// 2. 检查特定权限
return permissions.stream()
.anyMatch(permission ->
permission.getServerId().equals(serverId) &&
permission.getPermissionType().equals(permissionType) &&
permission.isEnabled() &&
(permission.getExpireTime() == null || permission.getExpireTime().isAfter(LocalDateTime.now()))
);

} catch (Exception e) {
log.error("检查用户权限失败: userId={}, serverId={}, permissionType={}",
userId, serverId, permissionType, e);
return false;
}
}

/**
* 添加用户权限
* @param permission 权限
*/
public void addPermission(Permission permission) {
try {
// 1. 添加到用户权限
userPermissions.computeIfAbsent(permission.getUserId(), k -> new HashSet<>())
.add(permission);

// 2. 添加到服务器权限
serverPermissions.computeIfAbsent(permission.getServerId(), k -> new HashSet<>())
.add(permission);

log.info("用户权限添加成功: userId={}, serverId={}, permissionType={}",
permission.getUserId(), permission.getServerId(), permission.getPermissionType());

} catch (Exception e) {
log.error("添加用户权限失败", e);
throw new BusinessException("添加用户权限失败: " + e.getMessage());
}
}

/**
* 移除用户权限
* @param userId 用户ID
* @param serverId 服务器ID
* @param permissionType 权限类型
*/
public void removePermission(Long userId, Long serverId, String permissionType) {
try {
// 1. 从用户权限中移除
Set<Permission> userPerms = userPermissions.get(userId);
if (userPerms != null) {
userPerms.removeIf(permission ->
permission.getServerId().equals(serverId) &&
permission.getPermissionType().equals(permissionType)
);
}

// 2. 从服务器权限中移除
Set<Permission> serverPerms = serverPermissions.get(serverId);
if (serverPerms != null) {
serverPerms.removeIf(permission ->
permission.getUserId().equals(userId) &&
permission.getPermissionType().equals(permissionType)
);
}

log.info("用户权限移除成功: userId={}, serverId={}, permissionType={}",
userId, serverId, permissionType);

} catch (Exception e) {
log.error("移除用户权限失败", e);
throw new BusinessException("移除用户权限失败: " + e.getMessage());
}
}

/**
* 获取用户权限列表
* @param userId 用户ID
* @return 权限列表
*/
public List<Permission> getUserPermissions(Long userId) {
Set<Permission> permissions = userPermissions.get(userId);
return permissions != null ? new ArrayList<>(permissions) : new ArrayList<>();
}

/**
* 获取服务器权限列表
* @param serverId 服务器ID
* @return 权限列表
*/
public List<Permission> getServerPermissions(Long serverId) {
Set<Permission> permissions = serverPermissions.get(serverId);
return permissions != null ? new ArrayList<>(permissions) : new ArrayList<>();
}
}

6. 审计日志服务

6.1 审计日志服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/**
* 审计日志服务
*/
@Service
public class AuditLogService {

private final List<AuditLog> auditLogs = new CopyOnWriteArrayList<>();

/**
* 记录审计日志
* @param userId 用户ID
* @param username 用户名
* @param action 操作
* @param resource 资源
* @param result 结果
* @param details 详情
*/
public void recordAuditLog(Long userId, String username, String action,
String resource, String result, String details) {
try {
AuditLog auditLog = AuditLog.builder()
.userId(userId)
.username(username)
.action(action)
.resource(resource)
.result(result)
.details(details)
.clientIp(getClientIp())
.timestamp(LocalDateTime.now())
.build();

auditLogs.add(auditLog);

log.info("审计日志记录成功: userId={}, action={}, resource={}, result={}",
userId, action, resource, result);

} catch (Exception e) {
log.error("记录审计日志失败", e);
}
}

/**
* 获取审计日志
* @param userId 用户ID
* @param startTime 开始时间
* @param endTime 结束时间
* @return 审计日志列表
*/
public List<AuditLog> getAuditLogs(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
return auditLogs.stream()
.filter(log -> userId == null || log.getUserId().equals(userId))
.filter(log -> startTime == null || log.getTimestamp().isAfter(startTime))
.filter(log -> endTime == null || log.getTimestamp().isBefore(endTime))
.sorted(Comparator.comparing(AuditLog::getTimestamp).reversed())
.collect(Collectors.toList());
}

/**
* 获取客户端IP
* @return 客户端IP
*/
private String getClientIp() {
// 实现获取客户端IP的逻辑
return "127.0.0.1";
}
}

7. 堡垒机控制器

7.1 堡垒机控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/**
* 堡垒机控制器
*/
@RestController
@RequestMapping("/bastion")
public class BastionHostController {

@Autowired
private SSHConnectionManager sshConnectionManager;

@Autowired
private PermissionManager permissionManager;

@Autowired
private AuditLogService auditLogService;

/**
* 建立SSH连接
*/
@PostMapping("/connect")
public ResponseEntity<Map<String, Object>> connectSSH(
@RequestParam Long serverId,
@RequestParam Long userId) {
try {
// 1. 检查权限
if (!permissionManager.checkPermission(userId, serverId, "READ")) {
throw new BusinessException("没有访问权限");
}

// 2. 获取目标服务器信息
TargetServer targetServer = getTargetServer(serverId);

// 3. 建立SSH连接
SSHSession session = sshConnectionManager.createSSHConnection(userId, serverId, targetServer);

// 4. 记录审计日志
auditLogService.recordAuditLog(userId, "USER", "SSH_CONNECT",
"server:" + serverId, "SUCCESS", "建立SSH连接");

// 5. 构建响应
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("sessionId", session.getSessionId());
response.put("message", "SSH连接建立成功");

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("建立SSH连接失败", e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "建立SSH连接失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}

/**
* 执行SSH命令
*/
@PostMapping("/execute")
public ResponseEntity<Map<String, Object>> executeCommand(
@RequestParam String sessionId,
@RequestParam String command,
@RequestParam Long userId) {
try {
// 1. 检查权限
SSHSession session = sshConnectionManager.getActiveSessions().stream()
.filter(s -> s.getSessionId().equals(sessionId))
.findFirst()
.orElse(null);

if (session == null) {
throw new BusinessException("会话不存在");
}

if (!permissionManager.checkPermission(userId, session.getServerId(), "EXECUTE")) {
throw new BusinessException("没有执行权限");
}

// 2. 执行命令
CommandResult result = sshConnectionManager.executeCommand(sessionId, command);

// 3. 记录审计日志
auditLogService.recordAuditLog(userId, "USER", "COMMAND_EXECUTE",
"command:" + command, result.isSuccess() ? "SUCCESS" : "FAILED",
"命令执行结果: " + result.getOutput());

// 4. 构建响应
Map<String, Object> response = new HashMap<>();
response.put("success", result.isSuccess());
response.put("output", result.getOutput());
response.put("error", result.getError());
response.put("exitStatus", result.getExitStatus());

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("执行SSH命令失败", e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "执行SSH命令失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}

/**
* 关闭SSH连接
*/
@PostMapping("/disconnect")
public ResponseEntity<Map<String, Object>> disconnectSSH(
@RequestParam String sessionId,
@RequestParam Long userId) {
try {
// 1. 关闭SSH连接
sshConnectionManager.closeSSHConnection(sessionId);

// 2. 记录审计日志
auditLogService.recordAuditLog(userId, "USER", "SSH_DISCONNECT",
"session:" + sessionId, "SUCCESS", "关闭SSH连接");

// 3. 构建响应
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("message", "SSH连接关闭成功");

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("关闭SSH连接失败", e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "关闭SSH连接失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}

/**
* 获取活跃会话列表
*/
@GetMapping("/sessions")
public ResponseEntity<Map<String, Object>> getActiveSessions() {
try {
List<SSHSession> sessions = sshConnectionManager.getActiveSessions();

Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("sessions", sessions);

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("获取活跃会话列表失败", e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "获取活跃会话列表失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}

/**
* 获取审计日志
*/
@GetMapping("/audit-logs")
public ResponseEntity<Map<String, Object>> getAuditLogs(
@RequestParam(required = false) Long userId,
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
try {
List<AuditLog> logs = auditLogService.getAuditLogs(userId, startTime, endTime);

Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("logs", logs);

return ResponseEntity.ok(response);

} catch (Exception e) {
log.error("获取审计日志失败", e);

Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("message", "获取审计日志失败: " + e.getMessage());

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}

/**
* 获取目标服务器信息
* @param serverId 服务器ID
* @return 目标服务器
*/
private TargetServer getTargetServer(Long serverId) {
// 实现获取目标服务器信息的逻辑
return TargetServer.builder()
.id(serverId)
.name("测试服务器")
.host("192.168.1.100")
.port(22)
.username("root")
.password("password")
.build();
}
}

8. 总结

通过堡垒机的实现,我们成功构建了一个安全的SSH代理和权限管理系统。关键特性包括:

8.1 核心优势

  1. SSH代理: 安全的SSH连接代理和管理
  2. 权限管理: 细粒度的用户权限控制
  3. 审计日志: 完整的操作审计和日志记录
  4. 安全管理: 安全策略和访问控制
  5. 会话管理: 实时会话监控和管理

8.2 最佳实践

  1. 安全设计: 完善的权限控制和访问管理
  2. 审计记录: 详细的操作审计和日志记录
  3. 会话管理: 实时会话监控和超时处理
  4. 错误处理: 完善的异常处理和错误提示
  5. 性能优化: 高效的连接管理和资源控制

这套堡垒机方案不仅能够提供安全的SSH代理能力,还包含了权限管理、审计日志、会话管理等核心功能,是企业级网络安全的重要工具。