这是我的Spring Boot Blog帖子系列的第三篇文章。 在第一篇文章中,我谈到了我使用Spring Boot创建RESTFul Services的经验。 然后我将样本扩展到
与Swagger文档集成 。 在这篇文章中,我将在安全方面扩展上述示例。

什么是API安全性

API安全性广泛,具有许多不同的定义,含义和解决方案。 API安全性中的主要关键术语是授权,身份验证,加密,联合和委派。 但是,在这里我不会谈论它们。

什么是认证

身份验证用于可靠地确定最终用户的身份,并根据正确标识的用户授予对资源的访问权限。

什么是基本身份验证

基本身份验证是对资源实施访问控制的最简单方法。 在此,HTTP用户代理在发出请求时提供用户名和密码。 当需要身份验证时,包含用户名和密码的字符串由冒号分隔,并在发送到后端之前经过Base64编码。

如何调用基本身份验证受保护的API

选项1:发送授权标头。 该值是base64编码的username:password Ex:“授权:基本Y2hhbmRhbmE6Y2hhbmRhbmE =”

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

选项2:使用网址:

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

好的,我们讨论了一些基本的东西。 因此,让我们来看一下如何使用Spring Security保护REST API。 您可以从我的GitHub存储库下载初始示例代码(Swagger Spring Boot Project源代码)

为了使用基本的auth安全性增强我们先前的示例,首先我将在pom文件中添加“ spring-boot-starter-security”和“ spring-boot-starter-tomcat”依赖项。

<!-- -->
        <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 Web安全支持。

@Configuration
@EnableSwagger2
@EnableWebSecurity
public class ApplicationConfig extends WebSecurityConfigurerAdapter {

重写的configure(HttpSecurity)方法用于定义哪些URL路径应该受到保护,哪些不应该受到保护。 在我的示例中,不需要“ /”和“ / api”路径进行任何身份验证,并且任何其他路径(例如:“ admin”)都应使用基本身份验证进行身份验证。

@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”的用户。 在那里,我为内存中的用户添加了用户名,密码和userole。

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

除此之外,您还可以看到我已将自动装配的BasicAuthenticationPoint添加到我的配置类中。 BasicAuthenticationEntryPoint类的目的是将“ WWW-Authenticate”标头设置为响应。 因此,Web浏览器将显示一个对话框,用于基于基本身份验证机制(WWW-Authenticate标头)输入用户名和密码

然后,您可以使用“ mvn spring-boot:run”运行示例。 当您访问“ localhost:8080 / api / hello / chandana”时,调用api不需要基本身份验证。 但是,如果您尝试访问“ localhost:8080 / admin / hello / chandana”,则需要提供基本的身份验证凭据才能访问资源。

AppConfig类:

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", "cnapagoda@gmail.com");  
     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类:

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();  
   }  
 }

翻译自: https://www.javacodegeeks.com/2017/10/secure-spring-boot-rest-api-using-basic-authentication.html