Статьи

API REST Secure Spring Boot с использованием базовой аутентификации

Это третий пост из моей серии постов в блоге Spring Boot. В самом первом посте я рассказал о своем опыте создания RESTFul Services с использованием Spring Boot. Затем я расширил образец до
интегрировать с документацией Swagger . В этом посте я собираюсь расширить пример выше с аспектом безопасности.

Что такое безопасность API

API Security — это широкая область с множеством различных определений, значений и решений. Основными ключевыми терминами безопасности API являются Авторизация, Аутентификация, Шифрование, Федерация и Делегирование. Однако я не буду говорить о каждом из них здесь.

Что такое аутентификация

Аутентификация используется для надежного определения личности конечного пользователя и предоставления доступа к ресурсам на основе правильно идентифицированного пользователя.

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

Базовая аутентификация — это самый простой способ обеспечить контроль доступа к ресурсам. Здесь, пользовательский агент HTTP предоставляет имя пользователя и пароль при выполнении запроса. Строка, содержащая имя пользователя и пароль, разделенные двоеточием, кодируется Base64 перед отправкой бэкэнду, когда требуется аутентификация.

Как вызвать Basic Auth Protected API

Вариант 1: Отправить заголовок авторизации. Это значение в кодировке base64: имя пользователя: пароль Пример: «Авторизация: Basic Y2hhbmRhbmE6Y2hhbmRhbmE =»

1
curl -X GET http://localhost:8080/admin/hello/chandana -H 'authorization: Basic Y2hhbmRhbmE6Y2hhbmRhbmE='

Вариант 2. Использование URL:

1
curl -X GET -u username:password  http://localhost:8080/admin/hello/chandana

ОК, мы говорили о базовых вещах. Итак, давайте посмотрим, как защитить REST API с помощью Spring Security. Вы можете загрузить исходный пример кода из моего репозитория GitHub (исходный код Swagger Spring Boot Project)

Чтобы улучшить наш предыдущий пример базовой безопасностью аутентификации, сначала я собираюсь добавить в файл pom зависимости «spring-boot-starter-security» и «spring-boot-starter-tomcat».

01
02
03
04
05
06
07
08
09
10
<!-- -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>

Следующим шагом является то, что наш класс конфигурации аннотируется аннотацией @EnableWebSecurity, а класс конфигурации расширяется из WebSecurityConfigurerAdapter. Аннотация EnableWebSecurity включит поддержку веб-безопасности Spring-Security.

1
2
3
4
@Configuration
@EnableSwagger2
@EnableWebSecurity
public class ApplicationConfig extends WebSecurityConfigurerAdapter {

Метод переопределенной конфигурации (HttpSecurity) используется для определения того, какие URL-пути должны быть защищены, а какие — нет. В моем примере пути «/» и «/ api» не требуют никакой аутентификации, а любые другие пути (например, «admin») должны проходить аутентификацию с базовой аутентификацией.

1
2
3
4
5
6
7
@Override
protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.authorizeRequests().antMatchers("/", "/api/**").permitAll()
        .anyRequest().authenticated();
        http.httpBasic().authenticationEntryPoint(basicAuthenticationPoint);
}

В методе configureGlobal (AuthenticationManagerBuilder) я создал пользовательское хранилище в памяти с пользователем «chandana». Там я добавил имя пользователя, пароль и роль пользователя для пользователя в памяти.

1
2
3
4
@Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("chandana").password("chandana").roles("USER");
    }

В дополнение к этому, вы можете видеть, что я добавил AutoAired BasicAuthenticationPoint, в мой класс конфигурации. Целью класса BasicAuthenticationEntryPoint является установка заголовка «WWW-Authenticate» для ответа. Таким образом, веб-браузеры будут отображать диалоговое окно для ввода имени пользователя и пароля на основе базового механизма аутентификации (заголовок WWW-Authenticate)

Затем вы можете запустить образец, используя «mvn spring-boot: run». Когда вы обращаетесь к «localhost: 8080 / api / hello / chandana», базовая аутентификация не требуется для вызова API. Однако если вы попытаетесь получить доступ к «localhost: 8080 / admin / hello / chandana», потребуется предоставить базовые учетные данные для доступа к ресурсу.

Класс AppConfig:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.chandana.helloworld.config; 
 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.configuration.EnableWebSecurity; 
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 
 import springfox.documentation.builders.ApiInfoBuilder; 
 import springfox.documentation.builders.PathSelectors; 
 import springfox.documentation.builders.RequestHandlerSelectors; 
 import springfox.documentation.service.ApiInfo; 
 import springfox.documentation.service.Contact; 
 import springfox.documentation.spi.DocumentationType; 
 import springfox.documentation.spring.web.plugins.Docket; 
 import springfox.documentation.swagger2.annotations.EnableSwagger2; 
 @Configuration 
 @EnableSwagger2 
 @EnableWebSecurity 
 public class ApplicationConfig extends WebSecurityConfigurerAdapter { 
   @Autowired 
   private BasicAuthenticationPoint basicAuthenticationPoint; 
   @Bean 
   public Docket api() { 
     return new Docket(DocumentationType.SWAGGER_2) 
         .apiInfo(getApiInfo()) 
         .select() 
         .apis(RequestHandlerSelectors.basePackage("com.chandana.helloworld.controllers")) 
         .paths(PathSelectors.any()) 
         .build(); 
   
   @Override 
   protected void configure(HttpSecurity http) throws Exception { 
     http.csrf().disable(); 
     http.authorizeRequests().antMatchers("/", "/api/**").permitAll() 
     .anyRequest().authenticated(); 
     http.httpBasic().authenticationEntryPoint(basicAuthenticationPoint); 
   
   private ApiInfo getApiInfo() { 
     Contact contact = new Contact("Chandana Napagoda", "http://blog.napagoda.com", "[email protected]"); 
     return new ApiInfoBuilder() 
         .title("Example Api Title"
         .description("Example Api Definition"
         .version("1.0.0"
         .license("Apache 2.0"
         .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0"
         .contact(contact) 
         .build(); 
   
   @Autowired 
   public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 
     auth.inMemoryAuthentication().withUser("chandana").password("chandana").roles("USER"); 
   
 }

Класс BasicAuthenticationEntryPoint:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.chandana.helloworld.config; 
 import org.springframework.security.core.AuthenticationException; 
 import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; 
 import org.springframework.stereotype.Component; 
 import java.io.IOException; 
 import java.io.PrintWriter; 
 import javax.servlet.ServletException; 
 import javax.servlet.http.HttpServletRequest; 
 import javax.servlet.http.HttpServletResponse; 
 @Component 
 public class BasicAuthenticationPoint extends BasicAuthenticationEntryPoint { 
   @Override 
   public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx) 
       throws IOException, ServletException { 
     response.addHeader("WWW-Authenticate", "Basic realm=" +getRealmName()); 
     response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 
     PrintWriter writer = response.getWriter(); 
     writer.println("HTTP Status 401 - " + authEx.getMessage()); 
   
   @Override 
   public void afterPropertiesSet() throws Exception { 
     setRealmName("Chandana"); 
     super.afterPropertiesSet(); 
   
 }

Вы также можете загрузить исходный код Spring Boot Basic Auth Project из моего репозитория GitHub.

См. Оригинальную статью здесь: Безопасный Spring Boot REST API с использованием базовой аутентификации

Мнения, высказанные участниками Java Code Geeks, являются их собственными.