Spring Boot 支持轻松绑定的理解是什么?
轻松绑定, 是一种属性名称不需要与环境属性的键匹配的方式。 在 Spring Boot, 轻松绑定适用于配置属性的类型安全绑定。 例如, 如果使用了带有 @ConfigurationPropertie 注释的 Bean 类中的属性 sampleProp, 那么它可以绑定到以下任何环境属性:
- sampleProp
- sample-Prop
- sample_Prop
- SAMPLE_PROP
Spring Boot 中的自动配置有什么理解? 如何禁用自动配置?
Auto-configuration 用于自动配置应用程序所需的配置。 例如, 如果在应用程序的类路径中有一个数据源 Bean, 那么它会自动配置 JDBC 模板。 在自动配置的帮助下, 您可以轻松地创建 Java 应用程序, 因为它可以自动配置所需的 Bean、 控制器等。
要禁用自动配置属性, 您必须排除 @EnableAutoConfiguration 属性, 在不希望应用该属性的场景中。
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}
如果类不在类路径中, 那么要排除自动配置, 你必须提到以下代码:
@EnableAutoConfiguration(excludeName={Sample.class})
除此之外, Spring Boot 还提供了通过使用 Spring .autoconfigure.exclude 属性来排除自动配置类列表的功能。 您可以继续, 并将其添加到应用程序中, 属性或添加以逗号分隔的多个类
在 Spring Boot 中 @RequestMapping 和@RestController 注释的用途是什么?
@RequestMapping:
- 该注释用于提供路由信息, 并告诉 Spring 任何HTTP 请求都必须映射到相应的方法。
- 要使用这个注释, 您必须导入org.springframework.web.bind.annotation.RequestMapping;
@RestController:
- 此注释用于将 @ResponseBody 和@Controller 注释添加到类中
- 要使用这个注释, 您必须导入org.springframework.web.bind.annotation.RestController;
如何在 Spring Boot 中启用 HTTP/2 支持
您可以在 Spring Boot by 中启用 HTTP/2 支持:server.http2.enabled=true
Spring Boot 2默认数据库连接池选择了HikariCP
Spring Boot 还提供了其它的哪些 Starter Project Options?
Spring Boot 也提供了其它的启动器项目包括,包括用于开发特定类型应用程序的典型依赖项。
- spring-boot-starter-web-services - SOAP Web Services;
- spring-boot-starter-web - Web 和 RESTful 应用程序;
- spring-boot-starter-test - 单元测试和集成测试;
- spring-boot-starter-jdbc - 传统的 JDBC;
- spring-boot-starter-hateoas - 为服务添加 HATEOAS 功能;
- spring-boot-starter-security - 使用 SpringSecurity 进行身份验证和授权;
- spring-boot-starter-data-jpa - 带有 Hibeernate 的 Spring Data JPA;
- spring-boot-starter-data-rest - 使用 Spring Data REST 公布简单的 REST 服务;
为什么要用 Spring Boot?
- (1)简化配置,不需要编写太多的xml配置文件;
- (2)基于Spring构建,使开发者快速入门,门槛很低;
- (3)SpringBoot可以创建独立运行的应用而不需要依赖于容器;
- (4)内置tomcat服务器,不需要打包成war包,可以直接放到tomcat中运行;
- (5)提供maven极简配置,以及可视化的相关监控功能,比如性能监控,应用的健康程度等;
- (6)为微服务SpringCloud奠定了基础,使得微服务的构建变得简单;
- (7)Spring可以整合很多各式各样的框架,并能很好的集成;
Spring Boot 的核心配置文件有哪几个?它们的区别是什么?
SpringBoot的核心配置文件有application和bootstarp配置文件。
- application文件主要用于Springboot自动化配置文件。
- bootstarp文件主要有以下几种用途:
- 使用Spring Cloud Config注册中心时 需要在bootStarp配置文件中添加链接到配置中心的配置属性来加载外部配置中心的配置信息。
- 一些固定的不能被覆盖的属性
- 一些加密/解密的场景
Spring Boot 的配置文件有哪几种格式?它们有什么区别?
properties 和 .yml,它们的区别主要是书写格式不同。
1).properties: app.user.name = javastack
2).yml
app:
user:
name: javastack
另外,.yml 格式不支持 @PropertySource 注解导入配置。
Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?
- @SpringBootConfigurationa(加载的bean):加载相关的类中添加了@CompenScan+、@Repository、@Service、@Compent、@Controller类到beandefinitionMap中
- @EnableAutoConfigurationa(自动配置的类):@Import就是加载的INF下面的Spring.Factory的相关的配置类到beandefinitionMap的加载气的配置类。这里里面涉及到SPI技术。
- @Componentscan(扫描包)
开启 Spring Boot 特性有哪几种方式?
- 1)继承spring-boot-starter-parent项目
- 2)导入spring-boot-dependencies项目依赖
Spring Boot 需要独立的容器运行吗?
- 可以不需要,内置了 Tomcat/ Jetty 等容器。
运行 Spring Boot 有哪几种方式?
- 打包用命令或者放到容器中运行
- 用 Maven/ Gradle 插件运行
- 直接执行 main 方法运行
Spring Boot 自动配置原理是什么?
在分析原理之前先来整体的看一下自动配置的核心原理图,作一个简单的了解。\
简单来说,Spring Boot通过@EnableAutoConfiguration注解开启自动配置,对jar包下的spring.factories文件进行扫描,这个文件中包含了可以进行自动配置的类,当满足@Condition注解指定的条件时,便在依赖的支持下进行实例化,注册到Spring容器中。
在启动类中可以看到@SpringBootApplication注解,它是SpringBoot的核心注解,是一个组合注解。我们进入这个注解可以看到里面又包含了其它很多注解,但其中@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个注解尤为重要。
@SpringBootConfiguration:继承自Configuration,支持JavaConfig的方式进行配置。
@EnableAutoConfiguration:@Import就是加载的INF下面的Spring.Factory的相关的配置类到beandefinitionMap的加载气的配置类。这里里面涉及到SPI技术。
@ComponentScan:自动扫描组件,默认扫描该类所在包及其子包下所有带有指定注解的类,将它们自动装配到bean容器中,会被自动装配的注解包括@Controller、@Service、@Component、@Repository等。也可以指定扫描路径。
@EnableAutoConfiguration
继续进入@EnableAutoConfiguration,注意到这两个注解:@AutoConfigurationPackage和@Import,这里我们需要关心的是这个@Import注解.
@Import
观察@Import(AutoConfigurationImportSelector.class)注解,这里导入了AutoConfigurationImportSelector类。这个类中有一个非常重要的方法——selectImports(),它几乎涵盖了组件自动装配的所有处理逻辑,包括获得候选配置类、配置类去重、排除不需要的配置类、过滤等,最终返回符合条件的自动配置类的全限定名数组。下面源码图中对该方法进行了详尽的注释。
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//检查自动配置功能是否开启,默认开启
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
//加载自动配置的元信息
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//获取候选配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
//去掉重复的配置类
configurations = removeDuplicates(configurations);
//获得注解中被exclude和excludeName排除的类的集合
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
//检查被排除类是否可实例化、是否被自动注册配置所使用,不符合条件则抛出异常
checkExcludedClasses(configurations, exclusions);
//从候选配置类中去除掉被排除的类
configurations.removeAll(exclusions);
//过滤
configurations = filter(configurations, autoConfigurationMetadata);
//将配置类和排除类通过事件传入到监听器中
fireAutoConfigurationImportEvents(configurations, exclusions);
//最终返回符合条件的自动配置类的全限定名数组
return StringUtils.toStringArray(configurations);
}
这里需要关注的的是如何得到候选的配置类,可以看到所有的配置信息通过getCandidateConfigurations()得到,并最终由一个列表保存。我们继续查看getCandidateConfigurations()方法。
继续进入loadFactoryNames()方法,可以发现一个获取资源的可疑地址:FACTORIES_RESOURCE_LOCATION
再进入FACTORIES_RESOURCE_LOCATION,发现值为:META-INF/spring.factories
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
简述以上过程就是:getCandidateConfigurations()方法通过SpringFactoriesLoader加载器加载META-INF/spring.factories文件,通过这个文件获取到每个配置类的url,再通过这些url将它们封装成Properties对象,最后解析内容存于Map<String,List<String>>中。
下面是spring.factories文件的内容格式,根据它我们可以清晰地了解Map<String,List<String>>中都存了些什么。其中Key值为:org.springframework.boot.autoconfigure.EnableAutoConfiguration,Value值为后面的各种XXXAutoConfiguration类。
最后通过loadFactoryNames传递过来的class名称作为Key从Map中获得该类的配置列表,而这个class名称是什么呢?回到之前的SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader())方法,注意第一个参数,是一个方法,我们进入这个方法,发现返回的是EnableAutoConfiguration.class,这即是我们需要的class名称。
/**
* Return the class used by {@link SpringFactoriesLoader} to load configuration
* candidates.
* @return the factory class
*/
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
最终,getCandidateConfigurations()方法获取到了候选配置类并存于List中。之所以说是“候选”,是因为它们后续还需要经过一系列的去重、排除、过滤等操作,最终会通过selectImports()方法返回一个自动配置类的全限定名数组。
Spring Boot 的目录结构是怎样的?
src/main/java:存放代码
src/main/resources
- resources:(Spring Boot 默认的)存放资源文件
- static:(Spring Boot 默认的)存放静态文件,比如 css、js、image, (访问方式 http://localhost:8080/js/main.js)
- public:(Spring Boot 默认的)存放公共文件
- templates:(用户自己定义的,可以随便取名,但这里使用公认的文件名)存放静态页面,比如 jsp、html、tpl
- config:(用户自己定义的,可以随便取名,但这里使用公认的文件名)存放配置文件,比如 application.properties
你如何理解 Spring Boot 中的 Starters?
- Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成 Spring 及其他技术,而不需要到处找示例代码和依赖包。如你想使用 Spring JPA 访问数据库,只要加入 spring-boot-starter-data-jpa 启动器依赖就能使用了。
- Starters包含了许多项目中需要用到的依赖,它们能快速持续的运行,都是一系列得到支持的管理传递性依赖。
如何在 Spring Boot 启动的时候运行一些特定的代码?
可以实现接口 ApplicationRunner 或者 CommandLineRunner,这两个接口实现方式一样,它们都只提供了一个 run 方法。如果启动的时候有多个ApplicationRunner和CommandLineRunner,想控制它们的启动顺序,可以实现 org.springframework.core.Ordered接口或者使用 org.springframework.core.annotation.Order注解。
@FunctionalInterface
public interface CommandLineRunner {
/**
* Callback used to run the bean.
* @param args incoming main method arguments
* @throws Exception on error
*/
void run(String... args) throws Exception;
}
@FunctionalInterface
public interface ApplicationRunner {
/**
* Callback used to run the bean.
* @param args incoming application arguments
* @throws Exception on error
*/
void run(ApplicationArguments args) throws Exception;
}
----------------------------------------------------------------------------------------------------------
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class MyBean implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
// Do something...
}
}
@Bean
public CommandLineRunner init() {
return (String... strings) -> {
};
}
Spring Boot 有哪几种读取配置的方式?
从以上示例来看,Spring Boot可以通过@PropertySource,@Value,@Environment,@ConfigurationProperties来绑定变量。
读取application文件
在application.yml或者properties文件中添加:
info.address=USA
info.company=Spring
info.degree=high
1、@Value注解读取方式
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class InfoConfig1 {
@Value("${info.address}")
private String address;
@Value("${info.company}")
private String company;
@Value("${info.degree}")
private String degree;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getDegree() {
return degree;
}
public void setDegree(String degree) {
this.degree = degree;
}
}
2、@ConfigurationProperties注解读取方式
@Component
@ConfigurationProperties(prefix = "info")
public class InfoConfig2 {
private String address;
private String company;
private String degree;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getDegree() {
return degree;
}
public void setDegree(String degree) {
this.degree = degree;
}
}
读取指定文件
资源目录下建立config/db-config.properties:
db.username=root
db.password=123456
1、@PropertySource+@Value注解读取方式:注意:@PropertySource不支持yml文件读取。
@Component
@PropertySource(value = {"config/db-config.properties"})
public class DBConfig1 {
@Value("${db.username}")
private String username;
@Value("${db.password}")
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
2、@PropertySource+@ConfigurationProperties注解读取方式
@Component
@ConfigurationProperties(prefix = "db")
@PropertySource(value = {"config/db-config.properties"})
public class DBConfig2 {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Environment读取方式
以上所有加载出来的配置都可以通过Environment注入获取到。
@Autowired
private Environment env;
//获取参数
String getProperty(String key);
Spring Boot 支持哪些日志框架?推荐和默认的日志框架是哪个?
Spring Boot在所有内部日志中使用Commons Logging,但是默认配置也提供了对常用日志的支持,如:Java Util Logging,Log4J, Log4J2和Logback。每种Logger都可以通过配置使用控制台或者文件输出日志内容。
SLF4J——Simple Logging Facade For Java,它是一个针对于各类Java日志框架的统一Facade抽象。Java日志框架众多——常用的有java.util.logging, log4j, logback,commons-logging, Spring框架使用的是Jakarta Commons Logging API (JCL)。而SLF4J定义了统一的日志抽象接口,而真正的日志实现则是在运行时决定的——它提供了各类日志框架的binding。
Logback是log4j框架的作者开发的新一代日志框架,它效率更高、能够适应诸多的运行环境,同时天然支持SLF4J。
默认情况下,Spring Boot会用Logback来记录日志,并用INFO级别输出到控制台。在运行应用程序和其他例子时,你应该已经看到很多INFO级别的日志了。
SpringBoot 实现热部署有哪几种方式?
SpringBoot热部署方式一共有两种,分别使用两种不同的依赖。SpringBoot 1.3后才拥有SpringBoot devtools热部署
①:spring-boot-devtools ②:Spring Loaded
在项目的pom文件中添加依赖:
1 <!--热部署jar-->
2 <dependency>
3 <groupId>org.springframework.boot</groupId>
4 <artifactId>spring-boot-devtools</artifactId>
5 </dependency>
<build>
<plugins>
<plugin>
<!-- springBoot编译插件-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<!-- spring热部署 -->
<!-- 该依赖在此处下载不下来,可以放置在build标签外部下载完成后再粘贴进plugin中 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.6.RELEASE</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
你如何理解 Spring Boot 配置加载顺序?
1、开发者工具 `Devtools` 全局配置参数;
2、单元测试上的 `@TestPropertySource` 注解指定的参数;
3、单元测试上的 `@SpringBootTest` 注解指定的参数;
4、命令行指定的参数,如 `java -jar springboot.jar --name="Java技术栈"`;
5、命令行中的 `SPRING_APPLICATION_JSONJSON` 指定参数, 如 `java -Dspring.application.json='{"name":"Java技术栈"}' -jar springboot.jar`
6、`ServletConfig` 初始化参数;
7、`ServletContext` 初始化参数;
8、JNDI参数(如 `java:comp/env/spring.application.json`);
9、Java系统参数(来源:`System.getProperties()`);
10、操作系统环境变量参数;
11、`RandomValuePropertySource` 随机数,仅匹配:`ramdom.*`;
12、JAR包外面的配置文件参数(`application-{profile}.properties(YAML)`)
13、JAR包里面的配置文件参数(`application-{profile}.properties(YAML)`)
14、JAR包外面的配置文件参数(`application.properties(YAML)`)
15、JAR包里面的配置文件参数(`application.properties(YAML)`)
16、`@Configuration`配置文件上 `@PropertySource` 注解加载的参数;
17、默认参数(通过 `SpringApplication.setDefaultProperties` 指定);
Spring Boot 如何定义多套不同环境配置?
profile配置方式有两种:
- ·多profile文件方式:提供多个配置文件,每个代表一种环境。
- ·application-dev.properties/yml 开发环境
- ·application-test.properties/yml 测试环境
- ·application-pro.properties/yml 生产环境
profile激活三种方式:
- ·配置文件: 再配置文件中配置:spring.profiles.active=dev
- ·虚拟机参数:在VM options 指定:-Dspring.profiles.active=dev
- ·命令行参数:java –jar xxx.jar --spring.profiles.active=dev
但是考虑到一个问题,生产环境的配置文件的安全性,显然我们不能,也不应该把生产环境的配置文件放到项目仓库Git中,进行管理。一般我们将生产环境的配置文件放到生产环境的服务器中,以固定命令执行启动:java -jar myboot.jar --spring.config.location=/xx/yy/xx/application-prod.properties。或者,使用Jenkins在执行打包,配置上maven profile功能,使用服务器的配置文件。最后一种方式,使用配置中心管理配置文件;
Spring Boot 可以兼容老 Spring 项目吗,如何做?
可以兼容,使用 @ImportResource 注解导⼊⽼Spring 项目配置⽂件
保护 Spring Boot 应用有哪些方法?
使用的Https保证安全
传输层安全性(TLS)是HTTPS的官方名称,你可能听说过它称为SSL(安全套接字层),SSL是已弃用的名称,TLS是一种加密协议,可通过计算机网络提供安全通信。其主要目标是确保计算机应用程序之间的隐私和数据完整性。过去,TLS / SSL证书很昂贵,而且HTTPS被认为很慢,现在机器变得更快,已经解决了性能问题,Let's Encrypt提供免费的TLS证书,这两项发展改变了游戏,并使TLS成为主流。要在Spring Boot应用程序中强制使用HTTPS,您可以扩展WebSecurityConfigurerAdapter并要求安全连接。
@Configuration
public class WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requiresChannel().requiresSecure();
}
}
使用Snyk检查你的依赖关系
你很可能不知道应用程序使用了多少直接依赖项,这通常是正确的,尽管依赖性构成了整个应用程序的大部分。攻击者越来越多地针对开源依赖项,因为它们的重用为恶意黑客提供了许多受害者,确保应用程序的整个依赖关系树中没有已知的漏洞非常重要。
Snyk测试你的应用程序构建包,标记那些已知漏洞的依赖项。它在仪表板在应用程序中使用的软件包中存在的漏洞列表。此外,它还将建议升级的版本或提供补丁,并提供针对源代码存储库的拉取请求来修复您的安全问题。Snyk还确保在你的存储库上提交的任何拉取请求(通过webhooks)时都是通过自动测试的,以确保它们不会引入新的已知漏洞。每天都会在现有项目和库中发现新的漏洞,因此监控和保护生产部署也很重要。Snyk拍摄快照并监控你的部署,以便在发现新漏洞时,你可以通过JIRA,slack或电子邮件自动收到通知,并创建拉取请求以提供新漏洞的升级和补丁。Snyk可通过Web UI和CLI获得,因此您可以轻松地将其与CI环境集成,并将其配置为在存在严重性超出设定阈值的漏洞时中断构建。你可以免费使用Snyk进行开源项目或使用有限数量的私有项目。
升级更新新的版本
定期升级应用程序中的依赖项有多种原因。安全性是让您有升级动力的最重要原因之一。该start.spring.io起始页面采用了最新的春季版本的软件包,以及依赖关系,在可能的情况。基础架构升级通常不如依赖项升级具有破坏性,因为库作者对向后兼容性和版本之间的行为更改的敏感性各不相同。话虽如此,当你在配置中发现安全漏洞时,您有三种选择:升级,修补程序或忽略。在对应用程序进行必要的更改以使用较新版本之后,就应用程序的整体运行状况而言,升级是最安全的。
启用CSRF保护
跨站点请求伪造(Cross-Site Request Forgery )是一种攻击,强制用户在他们当前登录的应用程序中执行不需要的操作。如果用户是普通用户,一个成功攻击可能涉及请求的状态更改,如转移资金或更改其电子邮件地址,如果用户具有提升管理员的权限,则CSRF攻击可能会危及整个应用程序。Spring Security具有出色的CSRF支持,如果您正在使用Spring MVC的<form:form>标签或Thymeleaf @EnableWebSecurity,默认情况下处于启用状态,CSRF令牌将自动添加为隐藏输入字段。如果你使用的是像Angular或React这样的JavaScript框架,则需要配置CookieCsrfTokenRepository以便JavaScript可以读取cookie。如果你正在使用Angular,这就是你需要做的。如果您使用的是React,则需要读取XSRF-TOKENcookie并将其作为X-XSRF-TOKEN标题发回。当请求通过HTTPS发生时,Spring Security会自动加入一个secure标识到XSRF-TOKENcookie 。Spring Security对于CSRF cookie不使用SameSite=strict 的标志,但它在使用Spring Session或WebFlux会话处理时会使用,这对会话cookie有意义,因为它有助于识别用户,但是没有为CSRF cookie提供太多价值,因为CSRF令牌也需要在请求中。
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
}
使用内容安全策略防止XSS攻击
CSP是防止XSS攻击的良好防御,请记住,打开CSP能让CDN访问许多非常古老且易受攻击的JavaScript库,这意味着使用CDN不会为安全性增加太多价值。内容安全策略(CSP)是一个增加的安全层,可帮助缓解XSS(跨站点脚本)和数据注入攻击。要启用它,你需要配置应用程序以返回Content-Security-Policy标题。你还可以在HTML页面中<meta http-equiv="Content-Security-Policy">使用标记。
Spring安全性默认提供了许多安全标头:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Spring Security * 默认情况下不添加 CSP。你可以使用以下配置在Spring Boot应用程序中启用CSP标头。
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers()
.contentSecurityPolicy("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/");
}
}
使用OpenID Connect进行身份验证
OAuth 2.0是行业标准的授权协议。它使用scope来定义授权用户可以执行的操作的权限。但是,OAuth 2.0不是身份验证协议,并且不提供有关经过身份验证的用户的信息。OpenID Connect(OIDC)是一个OAuth 2.0扩展,提供用户信息,除了访问令牌之外,它还添加了ID令牌,以及/userinfo可以从中获取其他信息的端点,它还添加了发现功能和动态客户端注册的端点。如果使用OIDC进行身份验证,则无需担心如何存储用户、密码或对用户进行身份验证。相反,你可以使用身份提供商(IdP)为你执行此操作,你的IdP甚至可能提供多因素身份验证(MFA)等安全附加组件。要了解如何在Spring Boot应用程序中使用OIDC,请参阅Spring Security 5.0和OIDC入门。要总结如何使用它,你需要向项目添加一些依赖项,然后在application.yml文件中配置一些属性。
spring:
security:
oauth2:
client:
registration:
okta:
client-id: {clientId}
client-secret: {clientSecret}
scope: openid email profile
provider:
okta:
issuer-uri: https://{yourOktaDomain}/oauth2/default
管理密码?使用密码哈希!
以纯文本格式存储密码是最糟糕的事情之一。幸运的是,Spring Security默认情况下不允许使用纯文本密码。它还附带了一个加密模块,可用于对称加密,生成密钥和密码散列(也就是密码编码)。PasswordEncoder 是Spring Security中密码哈希的主要接口,如下所示:
public interface PasswordEncoder {
String encode(String rawPassword);
boolean matches(String rawPassword, String encodedPassword);
}
Spring Security提供了几种实现,最受欢迎的是BCryptPasswordEncoder和Pbkdf2PasswordEncoder。对于一般的密码管理,我们建议使用SCrypt或Argon2, SCrypt现在已经过时了(已经有一段时间了),并且有一个额外的复杂因素,BCrypt没有这个因素,这使得暴力破解变得加倍地困难。它由着名的密码学家/安全人员(Colin Percival)编写,在几乎所有编程语言中都有很好的库,SCrypt也得到Latacora的认可。Spring Security 5.1(即2018年9月下旬)将附带UserDetailsPasswordService API,允许您升级密码存储。
安全地存储秘密
应谨慎处理敏感信息,如密码,访问令牌等,你不能以纯文本形式传递,或者如果将它们保存在本地存储中。由于(GitHub)的历史已经一次又一次证明,开发人员并没有仔细考虑如何存储他们的秘密。一个好的做法是将保密信息存储在保管库中,该保管库可用于存储,提供对应用程序可能使用的服务的访问权限,甚至生成凭据。HashiCorp的Vault使得存储机密变得很轻松,并提供了许多额外的服务。如果您对此感兴趣,请务必花一些时间查看Spring Vault,它为HashiCorp Vault添加抽象,为客户提供基于Spring注释的访问,允许他们访问、存储和撤销机密而不会迷失在基础架构中。以下代码段显示了使用注释从Spring Vault中提取密码的方便程度。
@Value("${password}")
String password;
使用OWASP的ZAP测试您的应用程序
OWASP ZAP安全工具是针对在运行活动的应用程序进行渗透测试的代理。它是一个受欢迎的(超过4k星)免费的开源项目,托管在GitHub上。OWASP ZAP用于查找漏洞的两种方法是Spider和Active Scan。Spider工具以URL种子开头,它将访问并解析每个响应,识别超链接并将它们添加到列表中。然后,它将访问这些新找到的URL并以递归方式继续,为您的Web应用程序创建URL映射。Active Scan工具将根据潜在漏洞列表自动测试你选择的目标。它提供了一个报告,显示Web应用程序可被利用的位置以及有关漏洞的详细信息。
让你的安全团队进行代码审查
代码评审对任何高性能软件开发团队都至关重要。在Okta,我们所有的生产代码和官方开源项目都需要通过我们的专家安全团队进行分析,你的公司可能没有安全专家,但如果你正在处理敏感数据,也许你应该这样做!
Spring Boot 2.X 有什么新特性?与 1.X 有什么区别?
配置变更
- 在 2.x 中废除了一些 1.x 中的配置,并增加了许多新配置,详细请查看以下链接中的变更表格。
JDK 版本升级
- 2.x 至少需要 JDK 8 的支持,2.x 里面的许多方法应用了 JDK 8 的许多高级新特性,所以你要升级到 2.0 版本,先确认你的应用必须兼容 JDK 8。另外,2.x 开始了对 JDK 9 的支持。
第三方类库升级
- 1) Spring Framework 5+
- 2) Tomcat 8.5+
- 3) Flyway 5+
- 4) Hibernate 5.2+
- 5) Thymeleaf 3+
响应式 Spring 编程支持
- 2.x 通过启动器和自动配置全面支持 Spring 的响应式编程,响应式编程是完全异步和非阻塞的,它是基于事件驱动模型,而不是传统的线程模型。就连 Spring Boot 内部也对一些功能点进行了有必要的响应式升级,最值得注意的是对内嵌式容器的支持。
HTTP/2 支持
- 提供对HTTP/2 的支持,如:Tomcat, Undertow, Jetty,这个得依赖具体选择的应用服务器和应用环境。
配置属性绑定
- 在 1.x 中,配置绑定是通过注解
@ConfigurationProperties
来注入到 Spring 环境变量中的。在 2.x 中,配置绑定功能有了些的改造,在调整了 1.x 中许多不一致地方之外,还提供了独立于注解之外的 API 来装配配置属性。并增加了属性来源,这样你就能知道这些属性是从哪个配置文件中加载进来的。
Gradle 插件
- Spring Boot的 Gradle 插件全面重写了,并且最小支持 Gradle 4+ 以便提供一些重要的特性提升。
Kotlin
- 2.x 开始提供对 Kotlin 1.2 的支持,并且提供了一个
runApplication
函数来运行 Spring Boot 应用。
Spring Boot 有哪些优点?
1、独立运行:SpringBoot而且内嵌了各种servlet容器, Tomcat、Jetty等 ,现在不再需要打成war包部署 到容器中,Spring Boot只要打成- -个可执行的jar包就能独立运行,所有的依赖包都在一个jar包内。
2、简化配置:spring- boot- starter-web启动器自动依赖其他组件,简少了maven的配置。
3、自动配置:Spring Boot能根据当前类路径下的类、jar包来 自 动配置bean,如添加一个spring-boot- -starter-web启动器就能拥有web的功能,无需其他配置。
4、无代码生成和XML配置:Spring Boot配置过程中无代码生成,也无需XML配置文件就能完成所有配置工作,这一切都是借助于条件注解完成的,这也是Spring4.x的核心功能之一。
5、应用监控:Spring Boot提供一系列端点可以监控服务及应用,做健康检测。
Spring Boot的缺点:Spring Boot 虽然上手很容易,但如果你不了解其核心技术及流程,所以一旦遇到问题就很棘手,而且现在的解决方案也不是很多,需要一个完善的过程。
什么是 JavaConfig?
Spring JavaConfig是Spring社区的产品,他提供了配置Spring IOC容器的纯Java方法。因此它有助于避免使用XML配置。
1.面向对象的配置:由于配置被定义为JavaConfig中的类,因此用户可以充分使用Java中的面向对象功能。一个配置类可以继承另一个,重写它的@Bean方法等。
2.减少或者消除XML配置:提供了一种纯Java的方法来配置与XML配置概念相似的Spring容器。
3.类型安全和重构友好:提供了一种类型安全的方法了来配置spring容器,由于Java5.0对泛型的支持,现在可以按类型而不是名称检索bean,不需要任何的强制转换或者基于字符串的查找。
如何重新加载 Spring Boot 上的更改,而无需重新启动服务器?
这可以使用 DEV 工具来实现。通过这种依赖关系,您可以节省任何更改,嵌入式 tomcat将重新启动。Spring Boot 有一个开发工具(DevTools)模块,它有助于提高开发人员的生产力。Java 开发人员面临的一个主要挑战是将文件更改自动部署到服务器并自动重启服务器。开发人员可以重新加载 Spring Boot 上的更改,而无需重新启动服务器。这将消除每次手动部署更改的需要。Spring Boot 在发布它的第一个版本时没有这个功能。这是开发人员最需要的功能。DevTools 模块完全满足开发人员的需求。该模块将在生产环境中被禁用。它还提供 H2 数据库控制台以更好地测试应用程序。
SpringBoot热部署方式一共有两种,分别使用两种不同的依赖。SpringBoot 1.3后才拥有SpringBoot devtools热部署
①:spring-boot-devtools ②:Spring Loaded
在项目的pom文件中添加依赖:
1 <!--热部署jar-->
2 <dependency>
3 <groupId>org.springframework.boot</groupId>
4 <artifactId>spring-boot-devtools</artifactId>
5 </dependency>
<build>
<plugins>
<plugin>
<!-- springBoot编译插件-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<!-- spring热部署 -->
<!-- 该依赖在此处下载不下来,可以放置在build标签外部下载完成后再粘贴进plugin中 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.6.RELEASE</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
Spring Boot 中的监视器是什么?
Spring boot actuator是 spring启动框架中的重要功能之一。Spring boot监视器可帮助您访问生产环境中正在运行的应用程序的当前状态。有几个指标必须在生产环境中进行检查和监控。即使一些外部应用程序可能正在使用这些服务来向相关人员触发警报消息。监视器模块公开了一组可直接作为HTTP URL 访问的REST端点来检查状态。
如何在 Spring Boot 中禁用 Actuator 端点安全性?
默认情况下,所有敏感的 HTTP端点都是安全的,只有具有ACTUATOR 角色的用户才能访问它们。安全性是使用标准的 HttpServletRequest.isUserInRole方法实施的。我们可以使用来禁用安全性。只有在执行机构端点在防火墙后访问时,才建议禁用安全性。
如何在自定义端口上运行 Spring Boot 应用程序?
为了在自定义端口上运行Spring Boot应用程序,您可以在application.properties 中指定端口。server. port = 8090
如何实现 Spring Boot 应用程序的安全性?
为了实现Spring Boot的安全性,我们使用spring-boot-starter-security依赖项,并且必须添加安全配置。它只需要很少的代码。配置类将必须扩展WebSecurityConfigurerAdapter并覆盖其方法。
如何集成 Spring Boot 和 ActiveMQ?
对于集成Spring Boot和ActiveMQ,我们使用依赖关系。它只需要很少的配置,并且不需要样板代码。
如何使用 Spring Boot 实现分页和排序?
使用Spring Boot实现分页非常简单。使用Spring Data-JPA可以实现将可分页的传递给存储库方法。
什么是 Spring Profiles?
Spring Profiles 允许用户根据配置文件 ( dev, test, prod等)来注册 bean。因此,当应用程序在开发中运行时,只有某些bean可以加载,而在PRODUCTION中,某些其他 bean可以加载。假设我们的要求是Swagger文档仅适用于QA环境,并且禁用所有其他文档。这可以使用配置文件来完成。Spring Boot使得使用配置文件非常简单。
什么是 Spring Batch?
Spring Boot Batch 提供可重用的函数,这些函数在处理大量记录时非常重要,包括日志/跟踪,事务管理,作业处理统计信息,作业重新启动,跳过和资源管理。它还提供了更先进的技术服务和功能,通过优化和分区技术,可以实现极高批量和高性能批处理作业。简单以及复杂的大批量批处理作业可以高度可扩展的方式利用框架处理重要大量的信息。
如何使用 Spring Boot 实现异常处理?
Spring提供了一种使用ControllerAdvice处理异常的非常有用的方法。我们通过实现一个ControlerAdvice类,来处理控制器类抛出的所有异常。
您使用了哪些 starter maven 依赖项?
spring-boot-starter-activemq
spring-boot-starter-security
什么是 CSRF 攻击?
CSRF 代表跨站请求伪造。这是一种攻击,迫使最终用户在当前通过身份验证的Web应用程序上执行不需要的操作。CSRF 攻击专门针对状态改变请求,而不是数据窃取,因为攻击者无法查看对伪造请求的响应。