KrakenD集成Spring Security基础认证失效问题排查
问题排查:KrakenD网关调用Spring Security后端POST接口返回401未授权
我在Spring Security的SecurityAdapter中配置了内存用户(密码前缀{noop}表示明文),设置GET请求放行、其余请求需HTTP Basic认证。直接用Base64编码的认证头调用后端API正常,但通过KrakenD网关调用POST /apps接口时,返回401未授权错误(提示缺少Authorization请求头)。根据KrakenD文档,企业版基础认证需使用bcrypt,请求排查解决该问题。
后端Spring Security配置
SecurityAdapter代码
@Override public void configure(AuthenticationManagerBuilder auth) throws Exception { var authManager = auth.inMemoryAuthentication(); for (var user : userConfiguration.getUsers()) { authManager.withUser(user.getName()) .password("{noop}" + user.getPassword()) .roles(user.getRole()); } } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { // @formatter:off httpSecurity .csrf() .disable() .authorizeRequests() .antMatchers(HttpMethod.GET).permitAll() .anyRequest() .authenticated() .and() .httpBasic() .and() .exceptionHandling() .authenticationEntryPoint(authenticationEntryPoint()); // @formatter:on }
application.yml安全配置
security: users: - name: someUser password: somepwd role: someAdmin - name: ...
KrakenD网关配置(krakend.json)
{ "$schema": "https://www.krakend.io/schema/v3.json", "version": 3, "port": 9000, "timeout": "300000s", "cache_ttl": "4000s", "extra_config": { "router": { "return_error_msg": true } }, "endpoints": [ { "@comment": "Feature: POST boards with basic authentification", "endpoint": "/apps", "output_encoding": "no-op", "method": "POST", "backend": [ { "host": [ "http://ipaddress:4603" ], "method": "POST", "url_pattern": "/apps", "extra_config": { "modifier/martian": { "body.Modifier": { "scope": [ "request" ], "@comment": "Send a {'msg':'you rock!'}", "body": "Ym9hcm......" } } } } ] ... }
错误响应
{ "errors": [ { "status": 401, "title": "UNAUTHORIZED", "detail": "Full authentication is required to access this resource. Missing Authorization Key im Header." } ] }
解决方案
核心问题分析
- KrakenD未转发Authorization请求头:当前KrakenD配置未指定将客户端的Authorization头转发到后端服务,导致Spring Security无法获取认证信息,返回401。
- 企业版bcrypt适配需求:KrakenD企业版基础认证默认用bcrypt校验,后端当前使用明文
{noop},需统一认证方式或让KrakenD正确传递认证头。
方案1:配置KrakenD转发Authorization请求头
在KrakenD的endpoint配置中添加input_headers字段,明确指定转发Authorization头到后端:
{ "@comment": "Feature: POST boards with basic authentification", "endpoint": "/apps", "output_encoding": "no-op", "method": "POST", "input_headers": ["Authorization"], // 添加此行,指定转发认证头 "backend": [ { "host": [ "http://ipaddress:4603" ], "method": "POST", "url_pattern": "/apps", "extra_config": { "modifier/martian": { "body.Modifier": { "scope": [ "request" ], "@comment": "Send a {'msg':'you rock!'}", "body": "Ym9hcm......" } } } } ] }
方案2:适配KrakenD企业版bcrypt认证(网关统一校验)
如果希望由KrakenD网关统一处理基础认证,而非直接转发头到后端,需做以下修改:
- 后端修改密码存储为bcrypt:
移除{noop}前缀,改用bcrypt加密后的密码,并配置密码编码器:@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { var authManager = auth.inMemoryAuthentication().passwordEncoder(passwordEncoder()); for (var user : userConfiguration.getUsers()) { // 此时application.yml中的password需为bcrypt加密后的字符串 authManager.withUser(user.getName()) .password(user.getPassword()) .roles(user.getRole()); } } - KrakenD配置bcrypt基础认证:
在endpoint的extra_config中添加企业版认证配置:"extra_config": { "auth/basic": { "users": [ { "username": "someUser", "password": "$2a$10$EixZaY3sT7yyy97U5r0JmeP31O6V88kM", // bcrypt加密后的密码 "roles": ["someAdmin"] } ], "algorithm": "bcrypt" }, "modifier/martian": { // 原有body修改配置 } }
验证
- 重启KrakenD和后端服务
- 携带正确的Basic认证头调用KrakenD的
POST /apps接口 - 检查是否能正常访问后端并返回正确响应
内容的提问来源于stack exchange,提问作者emoleumassi
相关产品推荐
相关产品推荐

