SpringBoot+Keycloak无Bearer Token时返回HTML页面及自定义响应需求
解决SpringBoot+Keycloak无Token请求返回登录页的问题
问题原因
默认情况下Keycloak适配器会在认证失败(比如缺失Bearer Token)时重定向到登录页面,这对REST接口不友好——我们需要返回标准化的JSON错误响应而非HTML内容。
解决方案
1. 自定义认证入口点
创建一个类实现AuthenticationEntryPoint,专门处理未认证场景,返回自定义JSON:
import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; import java.util.Map; public class CustomAuthEntryPoint implements AuthenticationEntryPoint { private final ObjectMapper objectMapper = new ObjectMapper(); @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { response.setStatus(HttpStatus.UNAUTHORIZED.value()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); Map<String, Object> errorResp = new HashMap<>(); errorResp.put("code", 401); errorResp.put("msg", "请提供有效的Bearer Token进行认证"); errorResp.put("detail", authException.getMessage()); objectMapper.writeValue(response.getOutputStream(), errorResp); } }
2. 配置Spring Security
在Security配置类中替换默认的认证入口点,同时禁用表单登录、HTTP Basic等会触发重定向的机制:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.AuthenticationEntryPoint; import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider; @Configuration @EnableWebSecurity public class SecurityConfig { private final KeycloakAuthenticationProvider keycloakAuthProvider; public SecurityConfig(KeycloakAuthenticationProvider keycloakAuthProvider) { this.keycloakAuthProvider = keycloakAuthProvider; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { // 注册Keycloak认证提供者 http.authenticationProvider(keycloakAuthProvider); http .authorizeHttpRequests(auth -> auth .anyRequest().authenticated() ) // 配置Keycloak作为OAuth2资源服务器(新版适配方式) .oauth2ResourceServer(oauth2 -> oauth2.jwt()) // 替换为自定义认证入口点 .exceptionHandling(exceptions -> exceptions .authenticationEntryPoint(customAuthEntryPoint()) ) // 禁用CSRF(REST接口通常不需要) .csrf(csrf -> csrf.disable()) // 禁用默认表单登录和HTTP Basic,避免重定向到登录页 .formLogin(form -> form.disable()) .httpBasic(basic -> basic.disable()); return http.build(); } @Bean public AuthenticationEntryPoint customAuthEntryPoint() { return new CustomAuthEntryPoint(); } }
3. 关键配置补充(旧版Keycloak适配器)
如果你用的是spring-boot-starter-keycloak旧版适配器,需要在配置文件中添加以下参数,强制Keycloak以Bearer-only模式运行(不触发登录页重定向):
application.properties: keycloak.bearer-only=true keycloak.use-resource-role-mappings=true
验证
发送不带Bearer Token的请求到你的REST接口,此时应该收到401 Unauthorized状态码和自定义的JSON响应,不再返回Keycloak的HTML登录页面。
内容的提问来源于stack exchange,提问作者user2191287
相关产品推荐
相关产品推荐

