繁体   English   中英

单个端点的基于 API 密钥的身份验证

[英]API Key based authentication for a single endpoint

在我的 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 的身份验证,我更改了此代码。 经历了以下线程并相应地实施。 使用 API 密钥和秘密保护 Spring Boot API

Spring Security:多个 HTTP 配置不起作用

执行:

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 密钥的身份验证没有捕获它。 它进入基于登录的身份验证并返回未经授权的响应。

有什么帮助解决吗?

对于@Order注释,较低的值具有较高的优先级。 意味着您的用户名/密码身份验证首先触发。 并且说身份验证有一个.anyRequest()语句,导致它捕获所有请求。

排序较低的配置应该捕获特定的端点,而最高的是默认配置。 在您的情况下,这意味着 API 端点应该是@Order(1)并且默认应该是@Order

在不相关的注释上,我认为您应该从封装类中删除extends WebSecurityConfigurerAdapter并将@Configuration删除,因为它包含 spring 需要在启动时获取的配置属性,但不是WebSecurityConfigurerAdapter的实例,因为您的子类现在是

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM