这是我的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。
@Autowiredpublic 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(); } }
您也可以从我的GitHub存储库下载Spring Boot Basic Auth Project源代码。
翻译自: https://www.javacodegeeks.com/2017/10/secure-spring-boot-rest-api-using-basic-authentication.html