当前位置: 首页 > 知识库问答 >
问题:

具有多个身份验证提供程序的Spring Security Authentication Server,用于client_credentials

蒋弘致
2023-03-14

我正在尝试使用Spring Security authentication设置一个身份验证服务器,并且需要有多个身份验证提供程序来提供客户端\u凭据。

我已经进行了相当多的搜索,但尚未找到如何配置Spring Security以将我的自定义身份验证提供程序添加到客户端凭据身份验证提供程序列表中。我找到的每种方法都导致客户端凭据身份验证的相同2个提供程序。匿名和道身份验证提供程序。

如果您能帮助我了解如何为多个客户端凭据身份验证提供商配置Spring Security身份验证服务器,我将不胜感激。

授权服务器配置

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter 
{
    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(final AuthorizationServerSecurityConfigurer security) throws Exception {
        security.tokenKeyAccess("permitAll()")
            .checkTokenAccess("isAuthenticated()")
            .passwordEncoder(passwordEncoder())
            .allowFormAuthenticationForClients();
    }

    @Override
    public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()

            .withClient("sampleClientId").authorizedGrantTypes("implicit")
            .scopes("read", "write", "foo", "bar")
            .autoApprove(false)
            .accessTokenValiditySeconds(3600)
            .redirectUris("http://localhost:8083/")

            .and()

            .withClient("fooClientIdPassword")
            .secret(passwordEncoder().encode("secret"))
            .authorizedGrantTypes("password", "authorization_code", "refresh_token")
            .scopes("foo", "read", "write")
            .accessTokenValiditySeconds(3600)       // 1 hour
            .refreshTokenValiditySeconds(2592000)   // 30 days
            .redirectUris("xxx")

            .and()

            .withClient("barClientIdPassword")
            .secret(passwordEncoder().encode("secret"))
            .authorizedGrantTypes("client_credentials", "refresh_token")
            .scopes("bar", "read", "write")
            .resourceIds("kip-apis")
            .accessTokenValiditySeconds(3600)       // 1 hour
            .refreshTokenValiditySeconds(2592000)   // 30 days

            .and()

            .withClient("testImplicitClientId")
            .autoApprove(true)
            .authorizedGrantTypes("implicit")
            .scopes("read", "write", "foo", "bar")
            .redirectUris("xxx");
    }

    @Override
    public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain
            .setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter()));

        endpoints.authenticationManager(authenticationManager)
            .tokenServices(tokenServices())
            .tokenStore(tokenStore())
            .tokenEnhancer(tokenEnhancerChain);
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
         JwtAccessTokenConverter converter = new JwtAccessTokenConverter();        
        converter.setSigningKey("123");                
        return converter;
    }

    @Bean
    public TokenEnhancer tokenEnhancer() {
        return new CustomTokenEnhancer();
    }

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        defaultTokenServices.setTokenEnhancer(accessTokenConverter());
        return defaultTokenServices;
   }

   @Bean
   public BCryptPasswordEncoder passwordEncoder() {
       return new BCryptPasswordEncoder();
   }
}

网站安全配置:

@Configuration
@EnableWebSecurity( debug = true )  // turn off the default configuration 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .formLogin().disable() // disable form authentication
            .anonymous().disable() // disable anonymous user
            .authorizeRequests().anyRequest().denyAll(); // denying all access
    }

    @Autowired
    public void globalUserDetails(final AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
          .withUser("john").password(passwordEncoder.encode("123")).roles("USER").and()
          .withUser("tom").password(passwordEncoder.encode("111")).roles("ADMIN").and()
          .withUser("user1").password(passwordEncoder.encode("pass")).roles("USER").and()
          .withUser("admin").password(passwordEncoder.encode("nimda")).roles("ADMIN");
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }    
}

我尝试了几个选项,试图为客户端凭据授权添加额外的身份验证提供程序。比如在WebSecurity配置中。。。

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

它不起作用,在对客户端_凭据进行身份验证时,我没有看到添加到提供者列表中的自定义凭据,只有匿名和dao身份验证提供者。

共有1个答案

蔺翰音
2023-03-14

我终于能够获得Spring Security身份验证服务器的配置,以便我们可以为client_credentials添加多个提供程序。

@Configuration
@EnableAuthorizationServer
public class AuthenticationServerConfig  extends AuthorizationServerConfigurerAdapter {     
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.addTokenEndpointAuthenticationFilter(clientCredentialsTokenEndpointFilter());
    }

    @Bean
    protected ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter() {
        ClientCredentialsTokenEndpointFilter cctef = new CustomClientCredentialsTokenEndpointFilter();       
        cctef.setAuthenticationManager(clientAuthenticationManager());
        return cctef;
    }

    @Bean
    protected ProviderManager clientAuthenticationManager() {
        return new ProviderManager(Arrays.asList(authProvider()));
    }

    @Bean
    protected DaoAuthenticationProvider authProvider() {
        DaoAuthenticationProvider authProvider = new CustomDaoAuthenticationProvider();
        authProvider.setUserDetailsService(clientDetailsUserService());
        authProvider.setPasswordEncoder(passwordEncoder());
        return authProvider;
    }    

    @Bean
    protected BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    protected UserDetailsService clientDetailsUserService() {
        return new ClientDetailsUserDetailsService(clientDetailsService());
    }

    @Bean
    protected ClientDetailsService clientDetailsService() {     
        return new ClientDetailsService() {
            @Override
            public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
                BaseClientDetails details = new BaseClientDetails();
                details.setClientId("barClientIdPassword");
                details.setClientSecret(passwordEncoder().encode("secret"));
                details.setAuthorizedGrantTypes(Arrays.asList("client_credentials"));
                details.setScope(Arrays.asList("read", "trust"));
                details.setResourceIds(Arrays.asList("kip-apis"));
                Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
                authorities.add(new SimpleGrantedAuthority("ROLE_CLIENT"));
                details.setAuthorities(authorities);
                details.setAccessTokenValiditySeconds(3600);    //1hr
                details.setRegisteredRedirectUri(null);
                return details;
            }
        };
    }

    @Bean
    public AuthenticationEntryPoint oauthAuthenticationEntryPoint() {
        OAuth2AuthenticationEntryPoint aep = new OAuth2AuthenticationEntryPoint();
        aep.setRealmName("theRealm");
        return aep;     
    }
    @Bean
    public AuthenticationEntryPoint clientAuthenticationEntryPoint() {
        OAuth2AuthenticationEntryPoint aep = new OAuth2AuthenticationEntryPoint();
        aep.setRealmName("theRealm/client");
        return aep;     
    }

    @Bean
    public AccessDeniedHandler oauthAccessDeniedHandler() {
        return new OAuth2AccessDeniedHandler();
    }    
}

在clientAuthenticationManager中,我们现在可以将提供者添加到提供者管理器列表中。

我不确定这种方法是否完全正确,但它似乎确实允许我们做我们想做的事情。

 类似资料:
  • 问题内容: 使用Passport.js是否可以为同一路由指定多个身份验证提供程序? 例如(在护照指南中),我可以在以下示例路线中使用本地策略以及Facebook和Twitter策略吗? 问题答案: Passport的中间件的构建方式使您可以在一个呼叫中使用多种策略。 但是,它是用OR顺序定义的。也就是说,只有在所有策略均未成功返回的情况下,它才会失败。 这是您将如何使用它: 换句话说,使用它的方法

  • 我的问题是,我希望有两个身份验证提供商 之前:我有我的UserDetailServiceImpl,我根据数据库中的数据验证了用户的身份(不确定是哪个提供者) 现在:我使用了ActiveDirectoryLdapAuthentiation提供程序,如下所示 我成功了,所以我可以认证。 问题是: 我现在无法再使用数据库用户登录,现在只有LDAP。 未使用UserDetailsService,因此用户具

  • 我希望我的web应用程序的用户通过LDAP和额外的自定义身份验证进行身份验证。这是一个用Kotlin编写的Spring Boot应用程序。我将AuthenticationManagerBuilder配置为 我希望链接身份验证,以便如果CustomAuthenticationProvider成功地进行身份验证(函数authenticate不抛出),身份验证将继续使用LDAP身份验证提供程序。 正如所

  • 问题内容: 在Spring Security中,有多个身份验证提供程序的参考,但是找不到Java config中的示例。 以下链接给出了XML表示法: Spring Security中的多个身份验证提供程序 我们需要使用LDAP或DB进行身份验证 下面是我们的示例代码: 问题答案: 也许这会帮助你:

  • 我正在尝试在Spring身份验证服务器(Spring Security)中配置多个身份验证提供程序(主要和次要) 根据“身份验证”方法留档: 返回:包含凭据的完全经过身份验证的对象。如果AuthenticationProvider无法支持对传递的身份验证对象的身份验证,则可能返回null。在这种情况下,将尝试下一个支持提供的身份验证类的AuthenticationProvider。 如果身份验证失

  • 我正在尝试为正在进行的 spring-boot 项目实现身份验证和授权服务。我已经实现了一个基于 JPA 的身份验证提供程序,它工作正常。如何将 LDAP 身份验证提供程序添加到同一项目并根据用户身份验证类型在身份验证方法之间切换? 下面是我的代码 虽然我的LDAP证书是正确的,但它没有达到那个方法。如何从DB ex(LDAP、JPA、SSO)获取我的应用程序的身份验证方法,并执行相应的身份验证提