当额外使用OAuth2进行认证时,DaoAuthenticationProvider丢失

我发现了一个令人困惑的行为,它可能是故意的,但我无法确定是否如此。

当我使用Basic Authspecific oauth2 configuration时,DaoAuthenticationprovider'并没有被创建。如果在application.yaml`中没有这个特定的配置,一切都能正常工作。如果包含这个配置,我得到一个内部异常,导致401。我在下面描述了这两种情况。

我的问题是: 如果这是正确的行为,我如何在不提供自定义AuthenticationProvider等的情况下获得默认的Basic Auth运行?我没有尝试自己实现这一点,因为我不知道如何轻松实现它,而且,如果可能的话,我宁愿使用默认行为。

Basic Authentication does not work when

curl --location --request GET 'http://localhost:8080/actuator/info' --header 'Authorization: Basic dXNlcjpwYXNzd29yZA=='

响应

{"timestamp":"2021-05-25T13:25:30.198+00:00","status":401,"error":"Unauthorized","message":"","path":"/actuator/info"}

在Spring中,我得到一个ProviderNotFoundException

/actuator/info at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2021-05-25 15:23:32.727 DEBUG 4216 --- [nio-8080-exec-2] o.s.s.w.a.www.BasicAuthenticationFilter  : Basic Authentication Authorization header found for user 'user'
2021-05-25 15:23:32.730 DEBUG 4216 --- [nio-8080-exec-2] o.s.s.w.a.www.BasicAuthenticationFilter  : Authentication request for failed!
org.springframework.security.authentication.ProviderNotFoundException: No AuthenticationProvider found for org.springframework.security.authentication.UsernamePasswordAuthenticationToken
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:251) ~[spring-security-core-5.3.4.RELEASE.jar:5.3.4.RELEASE]

当调试时,我发现DaoAuthenticationProvider provider = new DaoAuthenticationProvider();InitializeUserDetailsBeanManagerConfigurer.java被配置时,***没有调用。事实上,InitializeUserDetailsBeanManagerConfigurer似乎并没有真正被调用来进行配置,我在这里登陆了GlobalAuthenticationConfigurerAdapter.java

To make everything work

我只需要从application.yaml中删除以下几行。

oauth2:
   resourceserver:
      jwt:
         issuer-uri: https://someissuer
         jwk-set-uri: https://somejwkuri

用curl访问,这次是200了

/actuator/info at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2021-05-25 15:51:21.845 DEBUG 16540 --- [nio-8080-exec-1] o.s.s.w.a.www.BasicAuthenticationFilter  : Basic Authentication Authorization header found for user 'user'
2021-05-25 15:51:21.845 DEBUG 16540 --- [nio-8080-exec-1] o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2021-05-25 15:51:22.036 DEBUG 16540 --- [nio-8080-exec-1] o.s.s.w.a.www.BasicAuthenticationFilter  : Authentication success: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@ed8ad585: Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ENDPOINT_ADMIN; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ENDPOINT_ADMIN

Code

application.yaml

还有其他的配置 flyway, hikari, camunda, 但所有这些都是独立的,并不影响我观察到的行为。

spring:
   security:
      oauth2:
         resourceserver:
            jwt:
               issuer-uri: https://someissuer
               jwk-set-uri: https://somejwkuri
      user:
         name: user
         password: password
         roles: ENDPOINT_ADMIN

server:
   port: 8080

management:
   endpoints:
      web:
         exposure:
            include: health,info,metrics,prometheus,loggers
         cors:
            allowed-origins: "*"
            allowed-methods: GET,POST
   security:
      enabled: false

logging:
   level:
      org:
         springframework: DEBUG
   pattern:
      console:%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n 

WebSecurityConfigurerAdapter extending class

它是一个内部类,因为我使用了多个过滤器链,但我在测试时排除了其他的过滤器–没有影响。

public class SecurityConfig {

    @Order(1)
    @Configuration
    public static class BasicAuthSecurityConfig extends WebSecurityConfigurerAdapter {
        // info is excluded on purpose
        private final String[] ENDPOINTS = { "health", "metrics", "prometheus", /* "info" */ }; 
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable().requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests()
                    .requestMatchers(EndpointRequest.to(ENDPOINTS)).permitAll()
                    .requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("ENDPOINT_ADMIN").and()
                    .httpBasic();
        }
    }

    // other commented out inner classes for oauth and general handling
}

build.gradle

非常简短的版本,但它应该说明这是在什么基础上建立的。

plugins {
    //Spring Boot
    id 'org.springframework.boot' version '2.3.3.RELEASE'
}

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-security'
    compile 'org.springframework.boot:spring-boot-starter-actuator'
    compile 'org.springframework.boot:spring-boot-starter-amqp'
    compile 'org.springframework.boot:spring-boot-starter-data-jpa'
    compile 'org.springframework.boot:spring-boot-starter-data-rest'
    compile 'org.springframework.boot:spring-boot-starter-web'
    compile 'org.springframework.cloud:spring-cloud-starter-kubernetes-config'
    compile 'org.springframework.cloud:spring-cloud-starter-openfeign'
    compile 'org.springframework.security:spring-security-oauth2-resource-server'
    compile 'org.springframework.security:spring-security-oauth2-jose'
    compile 'org.springframework.security:spring-security-config'
}

StackOverflow:java - DaoAuthenticationProvider missing when additionally using OAuth2 for Authentication - Stack Overflow