spring-security 针对单个端点的基于API密钥的身份验证

mpgws1up  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(175)

在我的spring Boot 应用程序中,我需要两种类型的身份验证机制。对于文件上传端点,它需要基于api-key的身份验证,而对于其他端点,它需要基于用户名密码的身份验证。以前,只有基于用户名密码的身份验证,如下所示。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.firewall.DefaultHttpFirewall;
import org.springframework.security.web.firewall.HttpFirewall;

//@Slf4j
/**
 * This class is used to setup security.
 * 
 *
 *
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  private static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfig.class);

  @Autowired
  private CustomAuthenticationProvider customAuthProvider;

  /**
   * This method to configure HTTP Security.
   * 
   * @param http
   *          - HttpSecurity
   */
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    LOGGER.info("Entered in the actuator security cofigure method");

    http.csrf().disable().authorizeRequests().antMatchers("/actuator/*").permitAll().anyRequest()
        .authenticated().and().httpBasic();
  }

  // Ignore basic auth for WSDL URL
  // Ignore basic auth for SWAGGER
  /**
   * This method to configure web security.
   * 
   * @param web
   *          - WebSecurity
   */
  @Override
  public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/**/*.wsdl").antMatchers("/**/*.wsdl$*")
                  .antMatchers("/v2/api-docs");
    web.httpFirewall(allowUrlEncodedSlashHttpFirewall());
  }

  /**
   * This method to configure Authentication Manager Builder.
   * 
   * @param auth
   *          - AuthenticationManagerBuilder
   */
  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(customAuthProvider);

  }

  @Bean
  public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
    DefaultHttpFirewall firewall = new DefaultHttpFirewall();
    firewall.setAllowUrlEncodedSlash(true);
    return firewall;
  }

}

为了支持基于api-key的身份验证,我修改了这段代码,如下所示。通过下面的线程并相应地实现。Securing Spring Boot API with API key and secret
Spring Security : Multiple HTTP Config not working
实施:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.firewall.DefaultHttpFirewall;
import org.springframework.security.web.firewall.HttpFirewall;

// @Slf4j
/**
 * This class is used to setup security.
 *
 * 
 */
@EnableWebSecurity
public class MultiSecurityConfig extends WebSecurityConfigurerAdapter {

  private static final Logger LOGGER = LoggerFactory.getLogger(MultiSecurityConfig.class);

  /**This method to configure HTTP Security. */
  @Configuration
  @Order(2)
  public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {

    @Value("${http.auth-token-header-name}")
    private String principalRequestHeader;

    @Value("${http.auth-token}")
    private String principalRequestValue;

    protected void configure(HttpSecurity http) throws Exception {
      APIKeyAuthFilter filter = new APIKeyAuthFilter(principalRequestHeader);
      filter.setAuthenticationManager(
          new AuthenticationManager() {

            @Override
            public Authentication authenticate(Authentication authentication)
                throws AuthenticationException {
              String principal = (String) authentication.getPrincipal();
              if (!principalRequestValue.equals(principal)) {
                throw new BadCredentialsException(
                    "The API key was not found or not the expected value.");
              }
              authentication.setAuthenticated(true);
              return authentication;
            }
          });
      http.csrf().disable().antMatcher("/**/file").authorizeRequests().anyRequest().authenticated();
    }
  }

  @Order(1)
  @Configuration
  public static class LoginSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired private CustomAuthenticationProvider customAuthProvider;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
      LOGGER.info("Entered in the actuator security cofigure method");

      http.csrf()
          .disable()
          .authorizeRequests()
          .antMatchers("/actuator/*")
          .permitAll()
          .anyRequest()
          .authenticated()
          .and()
          .httpBasic();
    }

    // Ignore basic auth for WSDL URL
    // Ignore basic auth for SWAGGER
    /**
     * This method to configure web security.
     *
     * @param web - WebSecurity
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
      web.ignoring()
          .antMatchers("/**/*.wsdl")
          .antMatchers("/**/*.wsdl$*")
          .antMatchers("/v2/api-docs");
      web.httpFirewall(allowUrlEncodedSlashHttpFirewall());
    }

    /**
     * This method to configure Authentication Manager Builder.
     *
     * @param auth - AuthenticationManagerBuilder
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.authenticationProvider(customAuthProvider);
    }

    @Bean
    public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
      DefaultHttpFirewall firewall = new DefaultHttpFirewall();
      firewall.setAllowUrlEncodedSlash(true);
      return firewall;
    }
  }
}

但是当我使用“/file”端点上传文件到服务器时,基于api密钥的身份验证似乎没有捕获它。它转到基于登录的身份验证,并返回一个未授权的响应。
能帮我修吗?

mrwjdhj3

mrwjdhj31#

对于@Order注解,较低的值具有较高的优先级。这意味着您的用户名/密码身份验证首先触发。并且所述身份验证具有.anyRequest()语句,该语句导致它捕获所有请求。
较低顺序的配置应该捕获特定的端点,而最高顺序的配置是默认值。
此外,您没有将过滤器添加到代码中的http对象,因此需要在它工作之前添加它
在一个不相关的注解中,我认为您应该从封装类中删除extends WebSecurityConfigurerAdapter,并将@Configuration删除到封装类中,因为它包含了spring需要在 Boot 时获取的配置属性,但它不是WebSecurityConfigurerAdapter的示例,因为您的子类现在是WebSecurityConfigurerAdapter的示例

相关问题