Spring Security暴露端点给未认证用户遇401,求解决方案
问题描述
需要暴露一个端点,允许所有用户(包括未登录用户)访问,但请求该端点时返回401 Unauthorized错误。
配置类代码
@EnableGlobalMethodSecurity(prePostEnabled = true) @ComponentScan(basePackageClasses = KeycloakSpringBootConfigResolver.class) @KeycloakConfiguration public class SecurityAuthenticationConfig extends KeycloakWebSecurityConfigurerAdapter { private static final String ANT_MATCHERS = "*/myEndPoint*"; private static final String WEB_SECURITY_ANT_MATCHERS = "*/myEndPoint*"; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) { KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider(); keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); auth.authenticationProvider(keycloakAuthenticationProvider); } @Bean public KeycloakConfigResolver keycloakConfigResolver() { return new KeycloakSpringBootConfigResolver(); } @Override protected void configure(final HttpSecurity http) throws Exception { super.configure(http); http.authorizeRequests() .antMatchers(ANT_MATCHERS) .permitAll() .anyRequest() .authenticated(); } @Bean @Override protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); } @Override public void configure(WebSecurity web) throws Exception { super.configure(web); web.ignoring().antMatchers(WEB_SECURITY_ANT_MATCHERS); } }
相关Spring日志
Securing POST /v1/myEndPoint/3 SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext KeycloakDeployment : Loaded URLs from http://localhost:8081/auth/realms/myRealm/.well-known/openid-configuration SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request Securing POST /error SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
解决方案
结合日志和配置分析,问题源于路径匹配规则错误以及多配置冲突,按以下步骤修复:
修正Ant路径匹配规则
当前"*/myEndPoint*"无法正确匹配/v1/myEndPoint/3这类带前缀的路径,改为"/**/myEndPoint/**",确保覆盖所有包含myEndPoint的层级路径。若端点路径固定,也可使用更精确的"/v1/myEndPoint/**"。移除WebSecurity的忽略配置
同时通过WebSecurity.ignoring()和HttpSecurity.permitAll()配置同一端点会导致规则冲突,删除configure(WebSecurity web)的重写代码,统一通过HttpSecurity管理权限控制。关闭CSRF保护(针对POST请求)
Spring Security默认开启CSRF防护,未登录用户发起POST请求会被拦截。在HttpSecurity配置中添加csrf().disable(),或针对目标端点单独关闭CSRF。
修改后的完整配置类代码:
@EnableGlobalMethodSecurity(prePostEnabled = true) @ComponentScan(basePackageClasses = KeycloakSpringBootConfigResolver.class) @KeycloakConfiguration public class SecurityAuthenticationConfig extends KeycloakWebSecurityConfigurerAdapter { private static final String PUBLIC_ENDPOINT = "/**/myEndPoint/**"; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) { KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider(); keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); auth.authenticationProvider(keycloakAuthenticationProvider); } @Bean public KeycloakConfigResolver keycloakConfigResolver() { return new KeycloakSpringBootConfigResolver(); } @Override protected void configure(final HttpSecurity http) throws Exception { super.configure(http); http.csrf().disable() .authorizeRequests() .antMatchers(PUBLIC_ENDPOINT) .permitAll() .anyRequest() .authenticated(); } @Bean @Override protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); } }
内容的提问来源于stack exchange,提问作者Talenel
相关产品推荐
相关产品推荐

