Spring security выдает ошибку 401 с действительным идентификатором клиента и секретом клиента

#spring-boot #spring-security #http-status-code-401

#spring-boot #spring-security #http-status-code-401

Вопрос:

У меня есть конечная точка REST приложения Spring boot 2, как показано ниже

 @DeleteMapping(value = "/deleteUser", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity deleteUser(HttpServletRequest pRequest,
                                 @RequestParam(value = "userId", required = true) String userId) {
    if (validateRequest(userId)) {
        try {
            response = myService.deleteUser(userId);
        } catch (Exception e) {
            logger.error("Exception");
        }
    } else {
        response = new ResponseEntity("Invalid user request.", new HttpHeaders(), HttpStatus.FORBIDDEN);
    }

    return response;
}
  

В приложении не применяется базовая аутентификация, но ограничение на конечную точку.
Клиент вызывает URL-адрес с действительными учетными данными:

 deleteUserUrl=https://xxxx,clientId=xxxx,clentSecret=xxx
  

получение ошибки:

 Full authentication is required to access this resource 
  

вот мой файл WebSecurityConfig. Этот доступ ограничен только определенной ролью.

   @Configuration
  @EnableWebSecurity
  public class WebSecurityConfig extends WebSEALSecurityConfig
 {

    @Value("${ldap.server.admin.group}")
    private String SERVER_ADMIN_GROUP;

    @Value("${app.user.group}")
    private String APP_GP_USER;

    @Autowired
    private AuthEntryPoint unauthorizedHandler; 
    //This class just to capture 401 error

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception
    {
           httpSecurity
             .authorizeRequests()
             .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
             .antMatchers("/actuator/health").permitAll()
             .antMatchers("/actuator/**").hasRole(SERVER_ADMIN_GROUP)
             .antMatchers("/test/deleteUser").hasRole(APP_GP_USER)
             .and().addFilterBefore(getCmpAuthenticationSelectionFilter(), 
             BasicAuthenticationFilter.class)
              .httpBasic()
              .authenticationEntryPoint(unauthorizedHandler)
             .and().csrf().disable()
            . sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
         }
     }
  

Вот мой класс фильтра CORS:

 @Configuration
public class CORSConfig {
    @Bean
    public CorsFilter corsFilter() {    
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}
  

Вот мой файл gradle:

   plugins {
     id 'org.springframework.boot' version '2.1.6.RELEASE'
     id 'java'
  }

  apply plugin: 'io.spring.dependency-management'
  apply plugin: 'java'
  apply plugin: 'eclipse'
  apply plugin: 'org.springframework.boot'
  apply plugin: 'jacoco'
  apply plugin: 'checkstyle'
  apply plugin: 'jdepend'

  sourceCompatibility = 1.11

  dependencies {
    implementation('org.springframework.boot:spring-boot-starter')
    compile('org.springframework.boot:spring-boot-starter-actuator')
    compile('org.springframework.boot:spring-boot-starter-cache')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.springframework.boot:spring-boot-starter-mail')
    implementation "com.company:webauth-plugin:2.0.1"
    implementation('org.springframework.boot:spring-boot-starter-security')

    compile('org.springframework.boot:spring-boot-starter-jdbc') {
       exclude group: 'org.apache.tomcat', module: 'tomcat-jdbc'
    }

    compile('org.apache.commons:commons-lang3:3.5')
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.apache.commons:commons-collections4:4.0')
    compile group: 'net.minidev', name: 'json-smart', version: '1.0.9'
    compile group: 'net.sf.jt400', name: 'jt400-jdk8', version: '9.5'
    compile('org.apache.httpcomponents:httpclient:4.3.4')
    compileOnly 'org.projectlombok:lombok'
    runtime('com.microsoft:sqljdbc4:4.0')

    testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test'
    testCompile group: 'junit', name: 'junit'

 }
  

файл application.properties:

   app.environment=${APP_ENV}
  server.servlet.context-path=${SERVER_CONTEXT_PATH}
  server.port=${SERVER_PORT}

  management.endpoints.web.exposure.include=*
  management.endpoint.shutdown.enabled=true
  management.health.ldap.enabled=false
  management.endpoints.web.cors.allow-credentials=true
  

Пожалуйста, обратите внимание: это перестало работать после внесения следующих изменений в приложение:

  1. Введение класса CORSConfig

  2. Удаление зависимости gradle

      compile group: 'org.springframework.security', name: 'spring-security-ldap', version: '5.1.2.RELEASE'
      
  3. Включен класс AuthEntryPoint для фиксации ошибки 401

Пожалуйста, посоветуйте, что я здесь делаю не так, заранее спасибо

Ответ №1:

Вы получаете ошибку 401. Это означает, что URL, к которому вы пытаетесь получить доступ, защищен. Поскольку вы говорите, что предоставили действительные учетные данные пользователя, то, возможно, у пользователя нет роли «APP_GP_USER»?

Я вижу, что вы передаете конфиденциальную информацию, такую как идентификатор клиента / секрет клиента, как часть URL-адреса запроса. Вероятно, вам следует пересмотреть это.

Передает ли клиент заголовок авторизации в запросе на удаление? Вам необходимо предоставить это, поскольку вы включили базовую аутентификацию в своем файле WebSecurityConfig через httpBasic() в методе configure.

Я бы посоветовал вам протестировать свои URL-адреса с помощью http-клиента, такого как postman.

Например, здесь я пытаюсь получить доступ к защищенному URL: http://localhost:8088/demo/home без предоставления базовой аутентификации. Обратите внимание, я получаю ошибку 401.

ошибка 401

И здесь я предоставил надлежащие учетные данные и поэтому получил правильный ответ. Обратите внимание, как postman добавил заголовок авторизации.

Добавлена базовая аутентификация

Успешный ответ

Комментарии:

1. Спасибо за подсказку, Навин, я добавил .httpBasic().disable(), чтобы api не применял базовую аутентификацию и включил пользовательский обработчик для отслеживания ошибок 403, поскольку httpbasic отключен, мы не должны ожидать 401. Я попросил команду пользовательского интерфейса передать роль в URL, чтобы проверить это