1. 概述
在这个教程中,我们将专注于测试一个使用Keycloak进行身份验证和授权的安全REST服务,并通过Swagger UI进行访问。
2. 挑战
像其他Web资源一样,REST API通常会受到保护。因此,服务消费者(如Swagger UI)不仅需要处理HTTP调用,还需要向服务提供者提供身份验证信息。
Keycloak是一个IAM服务器,它允许在服务提供者的实现之外进行身份验证和授权。这是架构的一部分,如下图所示:
我们可以看到,服务提供者和服务消费者都需要与Keycloak服务器通信。首先,我们需要安装一个Keycloak服务器并将其集成到Spring Boot应用中,作为REST服务提供者。然后,我们需要扩展Swagger UI。
3. 集成Swagger UI
要在Spring Boot和Swagger UI之间集成,只需将库添加到项目依赖列表中(无需额外配置):
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.5.0</version>
</dependency>
4. 使用标准
对于供应商特定的代码扩展Swagger UI,只有在特殊情况下才有意义。因此,我们应该优先选择供应商无关的标准。接下来的章节将描述如何实现这一点。
4.1. 存在的标准
首先,我们需要了解哪些标准存在。对于身份验证和授权,有OAuth2这样的协议。对于SSO,我们可以使用OpenID Connect(OIDC),它是OAuth2的扩展。
描述REST API的标准是OpenAPI。这个标准包括定义多个安全方案,包括OAuth2和OIDC:
paths:
/api/v1/products:
get:
...
security:
- my_oAuth_security_schema:
- read_access
...
securitySchemes:
my_oAuth_security_schema:
type: oauth2
flows:
implicit:
authorizationUrl: https://api.example.com/oauth2/authorize
scopes:
read_access: read data
write_access: modify data
4.2. 扩展服务提供者
在代码驱动的方法中,服务提供者可以根据代码自动生成OpenAPI文档。因此,也必须提供这些安全方案。例如,在使用Spring Boot和SpringDoc的情况下,我们可以编写这样一个配置类:
@Configuration
public class OpenAPISecurityConfig {
@Value("${keycloak.auth-server-url}")
String authServerUrl;
@Value("${keycloak.realm}")
String realm;
private static final String OAUTH_SCHEME_NAME = "my_oAuth_security_schema";
@Bean
public OpenAPI openAPI() {
return new OpenAPI().components(new Components()
.addSecuritySchemes(OAUTH_SCHEME_NAME, createOAuthScheme()))
.addSecurityItem(new SecurityRequirement().addList(OAUTH_SCHEME_NAME))
.info(new Info().title("Todos Management Service")
.description("A service providing todos.")
.version("1.0"));
}
private SecurityScheme createOAuthScheme() {
OAuthFlows flows = createOAuthFlows();
return new SecurityScheme().type(SecurityScheme.Type.OAUTH2)
.flows(flows);
}
private OAuthFlows createOAuthFlows() {
OAuthFlow flow = createAuthorizationCodeFlow();
return new OAuthFlows().implicit(flow);
}
private OAuthFlow createAuthorizationCodeFlow() {
return new OAuthFlow()
.authorizationUrl(authServerUrl + "/realms/" + realm + "/protocol/openid-connect/auth")
.scopes(new Scopes().addString("read_access", "read data")
.addString("write_access", "modify data"));
}
}
当然,使用其他技术会有不同的实现。但我们始终应该意识到必须生成的OpenAPI。
4.3. 扩展服务消费者
Swagger UI默认支持OpenAPI认证方案,无需自定义。我们将能够通过它进行身份验证:
其他客户端可能有不同的解决方案。例如,有一个NPM模块可以为Angular应用程序提供简单易用的OAuth2和OpenID Connect (OIDC)支持。
5. 通过Swagger UI测试端点
按照这篇文章提供的配置,您应该已经配置了一个用户,可以登录应用。为了使用Swagger UI,还需要配置客户端(login-app)并启用"隐式流身份验证方法":
还需要关联应用程序范围(读取和写入),首先在客户端范围会话中创建这些范围:
然后将它们添加到应用程序启用范围的列表中:
现在,您可以在地址http://localhost:8081/swagger-ui/index.html上访问[Swagger UI应用](/swagger-2-documentation-for-spring-rest-api),并使用正确的范围进行身份验证:
最后,我们可以通过Swagger访问控制器端点:
6. 总结
在这篇文章中,我们指出了在使用Keycloak作为IAM时,通过Swagger UI测试REST服务的可能性。最佳解决方案是使用OpenAPI、OAuth2和OpenID Connect等标准,这些工具都支持这些标准。
如往常一样,所有代码可在GitHub上获取。