gpt4 book ai didi

java - 使用 HTTP Basic 和 OIDC Bearer Token 的 Spring Security 身份验证

转载 作者:行者123 更新时间:2023-12-05 03:45:12 25 4
gpt4 key购买 nike

我正在开发一个使用 Spring Boot 2.4.1 和 Spring Security 5.4.2 的 Web 应用程序,我需要同时提供 HTTP 基本身份验证和 Bearer Token 身份验证(JWT 访问 token 是从 SPA 为每个 API 发送的称呼)。所有 API URL 都以路径 /api 开头,并且必须使用 Bearer Token 进行身份验证,除了两个 URL(/api/func1/api/func2 ) 是使用 HTTP Basic 所必需的。

问题是如果我为 HTTP Basic 激活扩展 WebSecurityConfigurerAdapter 的类,将跳过不记名 token 身份验证。

@Configuration
@EnableWebSecurity
@ConditionalOnProperty(name = "auth.enable", matchIfMissing = true)
@Order(1)
public class HttpBasicSecurityConfiguration extends WebSecurityConfigurerAdapter {

private final RestBasicAuthEntryPoint authenticationEntryPoint;
private final DataSource dataSource;

@Autowired
public HttpBasicSecurityConfiguration(final RestBasicAuthEntryPoint authenticationEntryPoint,
final DataSource dataSource) {
super();
this.authenticationEntryPoint = authenticationEntryPoint;
this.dataSource = dataSource;
}

@Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests().antMatchers({"/api/func1/**","/api/func2/**"}).authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint);
}

@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
// Usernames, passwords and roles are stored into USERS and AUTHORITIES tables
auth.jdbcAuthentication()
.passwordEncoder(passwordEncoder())
.dataSource(dataSource);
}

private PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}

@Configuration
@EnableWebSecurity(debug=true)
@ConditionalOnProperty(name = "auth.enable", matchIfMissing = true)
@Order(2)
public class Oauth2SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
public Oauth2SecurityConfiguration(CactusSystemConfiguration systemConfiguration) {
super();
this.systemConfiguration = systemConfiguration;
}

@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers({"/ws/**","/api/mock/**"}).permitAll()
.and()
.authorizeRequests().antMatchers("/api/**").authenticated()
.and()
.oauth2ResourceServer().jwt();
}
}

当调用需要使用不记名 token 进行身份验证的方法时,Spring Security 调试会打印以下信息:

Request received for GET '/api/genericFunc':

org.apache.catalina.connector.RequestFacade@517df0fb

servletPath:/api/genericFunc
pathInfo:null
headers:
host: devbox:8080
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0
accept: */*
accept-language: en-US,en;q=0.5
accept-encoding: gzip, deflate
authorization: Bearer eyJ0eXAiOiJ.....
connection: keep-alive
cookie: JSESSIONID=D3E8CED6AB13EFF0D15BFA6C69AFEED4; JSESSIONID=C923091B9B9E38A19106BC4F529F7D13


Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
LogoutFilter
BasicAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]

显然 BearerTokenAuthenticationFilter 没有加载。

如果我从运行中排除 HttpBasicSecurityConfiguration 那么我得到:

Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
LogoutFilter
BearerTokenAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]

知道为什么会这样吗?也许在具有相同祖先路径(即/api)的 API 中,Spring Security 中不可能有两种不同的身份验证方法

最佳答案

这是因为 HttpBasicSecurityConfiguration 匹配所有请求 所以只有 /api/func1/**/api/func2/** 根据 http 基本身份验证进行检查,而其他人则不需要进行身份验证。此时跳过 Spring 安全过滤器链,并且永远不会触发另一个过滤器。

您需要限制应用第一个过滤器的请求。只需将 HttpBasicSecurityConfiguration 中的 configure 方法更改为:

@Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf().disable()
.requestMatchers().antMatchers("/api/func1/**","/api/func2/**")
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint);
}

请注意 .requestMatchers().antMatchers("/api/func1/**","/api/func2/**").authorizeRequests() 之前应用。 anyRequest() 然后就可以使用任何请求了,不需要再去匹配url。

关于java - 使用 HTTP Basic 和 OIDC Bearer Token 的 Spring Security 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65996572/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com