使用Postman访问Spring Boot接口时Keycloak认证失败问题排查
问题解决:Postman携带Access Token访问Spring Boot接口返回认证页面
你的问题核心是当前Security配置仅支持浏览器端的OAuth2授权码流程(oauth2Login),未配置资源服务器模式来处理请求头中的Bearer Token。Postman直接携带Access Token的场景属于资源服务器模式,需要补充以下配置:
1. 补充资源服务器配置
在SecurityFilterChain中添加oauth2ResourceServer()配置,同时自定义JWT权限转换逻辑,确保和登录场景的权限提取规则一致:
@Configuration @EnableWebSecurity public class KeycloakSecurityConfig { @Value("${eval.required.role.name}") private String requiredRoleName; @Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}") private String jwkSetUri; @Bean CorsFilter corsFilter() { CorsFilter filter = new CorsFilter(); return filter; } @Bean protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); } @Bean SecurityFilterChain filterChain(HttpSecurity http, KeycloakLogoutHandler keycloakLogoutHandler) throws Exception { http.addFilterBefore(corsFilter(), SessionManagementFilter.class); http.authorizeRequests() .antMatchers("/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**", "/logout").authenticated() .anyRequest().hasAuthority(requiredRoleName); // 同时支持浏览器登录和资源服务器Token认证 http.oauth2Login(Customizer.withDefaults()) .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt .jwkSetUri(jwkSetUri) .jwtAuthenticationConverter(jwtAuthenticationConverter()))) .logout() .addLogoutHandler(keycloakLogoutHandler) .logoutSuccessUrl("/"); return http.build(); } // 自定义JWT权限转换器,从Token的"Roles"Claim中提取权限 @Bean JwtAuthenticationConverter jwtAuthenticationConverter() { JwtAuthenticationConverter converter = new JwtAuthenticationConverter(); converter.setJwtGrantedAuthoritiesConverter(jwt -> { List<String> roles = jwt.getClaim("Roles"); if (roles == null) { return Collections.emptyList(); } return roles.stream() .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); }); return converter; } @Component @RequiredArgsConstructor static class GrantedAuthoritiesMapperImpl implements GrantedAuthoritiesMapper { @Override public Collection<? extends GrantedAuthority> mapAuthorities(Collection<? extends GrantedAuthority> authorities) { Set<GrantedAuthority> mappedAuthorities = new HashSet<>(); authorities.forEach(authority -> { if (OidcUserAuthority.class.isInstance(authority)) { final var oidcUserAuthority = (OidcUserAuthority) authority; mappedAuthorities.addAll(extractAuthorities(oidcUserAuthority.getIdToken().getClaims())); } else if (OAuth2UserAuthority.class.isInstance(authority)) { try { final var oauth2UserAuthority = (OAuth2UserAuthority) authority; final var userAttributes = oauth2UserAuthority.getAttributes(); mappedAuthorities.addAll(extractAuthorities(userAttributes)); } catch (Exception e) { throw new RuntimeException(e); } } }); return mappedAuthorities; } @SuppressWarnings({"rawtypes", "unchecked"}) private static Collection<GrantedAuthority> extractAuthorities(Map<String, Object> claims) { if (claims != null) { ArrayList<String> roles = (ArrayList<String>) claims.get("Roles"); List<GrantedAuthority> authorities = new ArrayList<>(roles.size()); for (String role : roles) { authorities.add(new SimpleGrantedAuthority(role)); } return authorities; } return Collections.emptyList(); } } }
2. 配置Keycloak JWK地址
在application.properties(或application.yml)中添加Keycloak的公钥获取地址,用于验证JWT签名:
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://你的Keycloak地址/auth/realms/你的领域/protocol/openid-connect/certs
关键修改说明
oauth2ResourceServer():启用资源服务器模式,让Spring Security识别并处理请求头中的Authorization: Bearer {token}。jwtAuthenticationConverter():自定义权限转换逻辑,和登录场景的extractAuthorities逻辑对齐,确保从JWT的RolesClaim中提取角色权限。- JWK地址配置:Spring Security需要通过该地址获取Keycloak的公钥,验证Token的合法性。
完成以上修改后,Postman携带Access Token访问接口时,Spring Security会直接解析Token并验证权限,不再重定向到认证页面。
内容的提问来源于stack exchange,提问作者Octavia
相关产品推荐
相关产品推荐

