将自定义AuthenticationProvider添加到Spring Boot + oauth +oidc

2023-12-22

我使用 SpringBoot 2.1.7 和 Okta 提供身份验证服务开发了一个基本的 oauth/oidc 示例。这是我的 Gradle 依赖设置供参考:

plugins {
id 'org.springframework.boot' version '2.1.7.RELEASE'
id 'java'
}
apply plugin: 'io.spring.dependency-management'

sourceCompatibility = '1.8'

configurations {
  developmentOnly
  runtimeClasspath {
    extendsFrom developmentOnly
 }
}

repositories {
    mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.okta.spring:okta-spring-boot-starter:1.2.1'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
}

Okta 端的所有元素均已正确配置,并且该示例按预期工作。这里几乎是一个“hello world”类型的演示。我想添加一个自定义身份验证提供程序,该提供程序在 Spring 提供的所有其他 AuthenticationProvider 之后执行。我已经使用调试器单步调试了代​​码,并注意到 Spring 自动配置了几个 AuthenticationProvider。他们是:

  1. 匿名身份验证提供者
  2. OAuth2LoginAuthenticationProvider
  3. OidcAuthorizationCodeAuthenticationProvider
  4. OAuth2AuthorizationCodeAuthenticationProvider
  5. Jwt身份验证提供者

我希望将我的身份验证提供商置于第六位。我尝试了以下 WebSecurityConfig,即使配置(AuthenticationManagerBuilder authBuilder)方法触发,它也不起作用:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{

    @Autowired
    private CustomAuthenticationProvider customAuthenticationProvider;

    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
    http.authorizeRequests()
        .anyRequest().authenticated()
        .and()
        .oauth2Login()
        .successHandler(customOauthLoginSuccessHandler())
        .failureHandler(customOauthLoginFailureHandler())
        .and()
        .oauth2Client();
    http.csrf().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(customAuthenticationProvider);
    }

    @Bean
    public CustomOauthLoginSuccessHandler customOauthLoginSuccessHandler()
    {
        CustomOauthLoginSuccessHandler handler = new CustomOauthLoginSuccessHandler();
        return handler;
    }

    @Bean
    public CustomOauthLoginFailureHandler customOauthLoginFailureHandler()
    {
        CustomOauthLoginFailureHandler handler = new CustomOauthLoginFailureHandler();
        handler.setUseForward(true);
        handler.setDefaultFailureUrl("/oautherror");
        return handler;
    }

}

我的身份验证提供程序永远不会执行。这是我的自定义 AP:

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider
{
    private Logger logger = LoggerFactory.getLogger(CustomAuthenticationProvider.class);
    private CustomOidcUserService customOidcUserService;

    public CustomAuthenticationProvider(CustomOidcUserService customOidcUserService)
    {
        this.customOidcUserService = customOidcUserService;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException
    {
        logger.info("CustomAuthenticationProvider executing...");
        Object user = authentication.getPrincipal();
        if (user instanceof DefaultOidcUser)
        {
            logger.info("principal is instanceof DefaultOidcUser");
            DefaultOidcUser authToken = (DefaultOidcUser) user;
            this.customOidcUserService.loadUserByUsername(authToken.getClaims().get("preferred_username").toString());
            // add additional info to the Authentication object
        }

        return authentication;
    }

    @Override
    public boolean supports(Class<?> authentication)
    {
        return OAuth2LoginAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

我的主要目标是添加有关来自旧 Oracle 数据库的经过身份验证的用户的附加信息。无法将此附加信息添加到 Okta 端(在云中)。

请注意,我能够轻松地将成功和失败处理程序添加到身份验证路径中。我觉得 SpringBoot 自动配置的固有特性可能会妨碍我。只需要知道如何解决这个问题。

附加信息,yml 文件:

okta:
  oauth2:
    issuer: https://myhost.okta.com/oauth2/default
    client-id: 123456AAABBBCCC
    client-secret: AAAAAAAAABBBBBBBBBBB

我正在回答我自己的帖子,因为我确定这是错误的方法。运行多次测试后,我能够添加自定义 AuthenticationProvider (AP),但是如果先前的提供程序成功并返回结果,则不能保证我的提供程序将运行。这是 ProviderManager 类在每个 AP 中旋转时的默认行为。更好的方法是定义一个 CustomUserDetailsS​​ervice 来扩展 OidcUserService 或 DefaultOAuth2UserService。这是我更新的代码,可以回答我的问题:

// @Component is removed
public class CustomAuthenticationProvider implements AuthenticationProvider
{
    private Logger logger = LoggerFactory.getLogger(CustomAuthenticationProvider.class);
    private CustomOidcUserService customOidcUserService;

    public CustomAuthenticationProvider(CustomOidcUserService customOidcUserService)
    {
        this.customOidcUserService = customOidcUserService;
    }

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
{
    logger.info("CustomAuthenticationProvider executing...");
    Object user = authentication.getPrincipal();
    if (user instanceof DefaultOidcUser)
    {
        logger.info("principal is instanceof DefaultOidcUser");
        DefaultOidcUser authToken = (DefaultOidcUser) user;
        this.customOidcUserService.loadUserByUsername(authToken.getClaims().get("preferred_username").toString());
        // add additional info to the Authentication object
    }

    return authentication;
}

@Override
public boolean supports(Class<?> authentication)
{
    return OAuth2LoginAuthenticationToken.class.isAssignableFrom(authentication);
}
}

以下是我对 WebSecurityConfig 的更改:

    @Override
protected void configure(HttpSecurity http) throws Exception
{
    http.authorizeRequests()
        .anyRequest().authenticated()
        .and()
        .oauth2Login()
        .successHandler(customOauthLoginSuccessHandler())
        .failureHandler(customOauthLoginFailureHandler())
        .and()
        .oauth2Client()
        .and().authenticationProvider(new CustomAuthenticationProvider());

    http.csrf().disable();
}

此代码确实将额外的自定义 AP 添加到正确的内部存储的 AP 列表中。在这种情况下,我的自定义 AP 将添加到由 WebSecurityConfigurerAdapter$DefaultPasswordEncoderAuthenticationManagerBuilder 维护的列表中。 再说一次,我没有使用这种方法,所以这篇文章已经关闭。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将自定义AuthenticationProvider添加到Spring Boot + oauth +oidc 的相关文章

随机推荐