我希望能够通过使用Keycloak和Sping Boot Security的Swagger UI登录。到目前为止,我可以通过 Postman 使用bearer生成的token登录,但如何配置用户凭据登录?
安全配置:
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private static final String[] AUTH_WHITELIST = {"/swagger-resources", "/swagger-resources/**", "/configuration/ui",
"/configuration/security", "/swagger-ui.html", "/webjars/**", "/v3/api-docs/**", "v3/api-docs",
"/api/public/**", "/api/public/authenticate", "/actuator/*", "/swagger-ui/**", "/api-docs/**"};
private final JwtAuthConverter jwtAuthConverter;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable());
http.authorizeHttpRequests(auth -> auth.requestMatchers(AUTH_WHITELIST).permitAll().anyRequest().authenticated());
http.oauth2ResourceServer(o2 -> o2.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthConverter)));
http.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
return http.build();
}
}
转换器:
@Component
public class JwtAuthConverter implements Converter<Jwt, AbstractAuthenticationToken> {
private final JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
@Value("${jwt.auth.converter.principle_attribute}")
private String principleAttribute;
@Value("${jwt.auth.converter.resource-id}")
private String resourceId;
@Override
public AbstractAuthenticationToken convert(@NonNull Jwt jwt) {
Collection<GrantedAuthority> authorities = Stream.concat(jwtGrantedAuthoritiesConverter.convert(jwt).stream(), extractResourceRoles(jwt).stream()).collect(Collectors.toSet());
return new JwtAuthenticationToken(jwt, authorities, getPrincipleClaimName(jwt));
}
private String getPrincipleClaimName(Jwt jwt) {
String claimName = JwtClaimNames.SUB;
if (principleAttribute != null) {
claimName = principleAttribute;
}
return jwt.getClaim(claimName);
}
private Collection<? extends GrantedAuthority> extractResourceRoles(Jwt jwt) {
Map<String, Object> resourceAccess;
Map<String, Object> resource;
Collection<String> resourceRoles;
if (jwt.getClaim("resource_access") == null) {
return Set.of();
}
resourceAccess = jwt.getClaim("resource_access");
if (resourceAccess.get(resourceId) == null) {
return Set.of();
}
resource = (Map<String, Object>) resourceAccess.get(resourceId);
resourceRoles = (Collection<String>) resource.get("roles");
return resourceRoles.stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).collect(Collectors.toSet());
}
}
Swagger配置:
@Configuration
public class SwaggerConfig {
private static final String OAUTH_SCHEME_BEARER = "bearerAuth";
@Bean
public OpenAPI customizeOpenAPI() {
return new OpenAPI()
.addSecurityItem(new SecurityRequirement()
.addList(OAUTH_SCHEME_BEARER))
.components(new Components()
.addSecuritySchemes(OAUTH_SCHEME_BEARER, new SecurityScheme()
.name(OAUTH_SCHEME_BEARER)
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")));
}
}
任何建议或教程链接,将受到欢迎,我尝试了我能找到的,但没有运气。
2条答案
按热度按时间tmb3ates1#
根据我们在评论中的讨论,我认为你不能通过swagger访问应用程序的端点,并且根据你提供的代码,我可以说你应该改变你的swagger配置:
大概是这样的:
OpenApi配置类
在它之后,如果你将打开打开API URL(
...swagger-ui/index.html
),并点击Authorize
按钮后,它插入您的JWT
令牌在这里就像你在 Postman 所有将工作得很好。更新:
OAuth 2.0中的Authorization Code Flow是一个客户端(在您的案例中为postman)从授权服务器获取授权码,然后使用该代码从令牌服务器获取访问令牌的过程,之后它可以使用令牌(客户端)从资源服务器(您在
8081
上运行的应用程序)访问安全端点。这意味着swagger-ui不能被配置为获取token。关于这个主题的好文章oauth-authorization-code-grant-type
jljoyd4f2#
我不得不重写我的swagger配置,它看起来像这样:
我还必须在我的application.yml中添加一些配置
它现在工作,通过重定向到keycloak日志页面,我也预填充客户端ID和属性中的秘密,使其更容易。