springboot 学习与回顾--覆盖springboot自动配置

简介: 覆盖springboot自动配置。保护应用程序

全配置并不是大家都一样的,围绕应用程序安全有很多决策要做,spring boot不能替我们做决定。springboot 为安全提供了一下基本的自动配置,但是我们还需要自己覆盖一些配置以满足我们特定的安全需求。
# # # # 一、保护应用程序

想了解如何通过显示配置来覆盖自动配置。我们先从为阅读列表应用程序添加 spring Security来入手。

Spring Boot自动配置让应用程序的安全工作变得易如反掌,我们需要做的只是添加Security起步依赖。以Gradle为例,应添加如下依赖:
compile("org.springframework.boot:spring-boot-starter-security")
如果使用Maven,那么你要在项目的 块中加入如下 :

org.springframework.boot
spring-boot-starter-security

这样就搞定了!重新构建应用程序后运行即可,现在这就是一个安全的Web应用程序了!
Security起步依赖在应用程序的Classpath里添加了Spring Secuirty(和其他一些东西)。Classpath里有Spring Security后,自动配置就能介入其中创建一个基本的Spring Security配置。试着在浏览器里打开该应用程序,我们马上就会看到HTTP基础身份验证对话框。此处的用户名是user,密码就有点麻烦了。密码是在应用程序每次运行时随机生成后写入日志的,我们需要查找日志消息(默认写入标准输出),找到此类内容:
Using default security password: d9d8abe5-42b5-4f20-a32a-76ee3df658d9
虽然不能肯定,但我猜这个特定的安全配置并不是你的理想选择。首先,HTTP基础身份验证对话框有点粗糙,对用户并不友好。而且,我们一般不会开发这种只有一个用户的应用程序,而且用户还要从日志文件里找到自己的密码(如果你开发一个这样的用户程序,相信老板一会会找你和你的主管好好聊聊的)。因此,我们会希望修改Spring Security的一些配置,至少要有一个好看一些的登录页,还要有一个基于数据库或LDAP(Lightweight Directory AccessProtocol)用户存储的身份验证服务。
接下来让我们看看如何写出Spring Secuirty配置,覆盖自动配置的安全设置吧
# # # # 二、创建自定义安全配置

覆盖自动配置很简单,就当自动配置不存在,直接显式地写一段配置。这段显式配置的形式不限,Spring支持的XML和Groovy形式配置都可以。

在编写显式配置时,我们会专注于Java形式的配置。在Spring Security的场景下,这意味着写一个扩展了 WebSecurityConfigurerAdapter 的配置类。代码清单1的 SecurityConfig就是我们需要的东西。

import org.springframework.beans.factory.annotation.Autowired;
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 org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.
UsernameNotFoundException;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ReaderRepository readerRepository;
@Override

//要求登录READER角色
// 设置登录表单的路径protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").access("hasRole('READER')") 
.antMatchers("/**").permitAll()
.and()
.formLogin()
.loginPage("/login") 
.failureUrl("/login?error=true");
}
UserDetailsService
@Override
protected void configure(
AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(new UserDetailsService() {
# 定义自定义UserDetailsServices
@Override
public UserDetails loadUserByUsername(String username) 
throws UsernameNotFoundException {
return readerRepository.findOne(username);
}
});
}
}

SecurityConfig 是个非常基础的Spring Security配置,尽管如此,它还是完成了不少安全定制工作。通过这个自定义的安全配置类,我们让Spring Boot跳过了安全自动配置,转而使用我们的安全配置。
扩展了 WebSecurityConfigurerAdapter 的配置类可以覆盖两个不同的 configure() 方
法。在 SecurityConfig 里,第一个 configure() 方法指明,“/”( ReadingListController的方法映射到了该路径)的请求只有经过身份认证且拥有READER角色的用户才能访问。其他的所有请求路径向所有用户开放了访问权限。这里还将登录页和登录失败页(带有一个 error 属性)指定到了/login。
Spring Security为身份认证提供了众多选项,后端可以是JDBC(Java Database Connectivity)、
LDAP和内存用户存储。在这个应用程序中,我们会通过JPA用数据库来存储用户信息。第二个configure() 方法设置了一个自定义的 UserDetailsService ,这个服务可以是任意实现了UserDetailsService 的类,用于查找指定用户名的用户。代码清单2提供了一个匿名内部类实现,简单地调用了注入ReaderRepository (这是一个Spring Data JPA仓库接口)的 findOne()方法。

import org.springframework.data.jpa.repository.JpaRepository;
public interface ReaderRepository
extends JpaRepository<Reader, String> {
  
// 通过JPA持久化读者
  }

和 BookRepository 类似,你无需自己实现 ReaderRepository 。这是因为它扩展了
JpaRepository ,Spring Data JPA会在运行时自动创建它的实现。这为你提供了18个操作 Reader
实体的方法。
说到 Reader 实体, Reader 类(如代码清单3所示)就是最后一块拼图了,它就是一个简单的JPA实体,其中有几个字段用来存储用户名、密码和用户全名。

import java.util.Arrays;
import java.util.Collection;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
@Entity
public class Reader implements UserDetails {
private static final long serialVersionUID = 1L;
@Id
private String username;
private String fullname;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getFullname() {
return fullname;
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
// UserDetails methods
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Arrays.asList(new SimpleGrantedAuthority("READER"));
}

// 不过期,不加锁,
// 不禁用
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}

Reader 用了 @Entity 注解,所以这是一个JPA实体。 username 字段上有 @Id 注解,表明这是实体的ID。因为 username 应该能唯一标识一个Reader 。
我们还注意到 Reader 实现了 UserDetails 接口以及其中的方法,这样 Reader 就能代表Spring Security里的用户了。 getAuthorities() 方法被覆盖过了,始终会为用户授予READER权限。 isAccountNonExpired() 、 isAccountNonLocked() 、 isCredentialsNonExpired()和 isEnabled() 方法都返回 true ,这样读者账户就不会过期,不会被锁定,也不会被撤销。重新构建并重启应用程序后,能以读者身份登录应用程序了。
想要覆盖Spring Boot的自动配置,我们要做的仅仅是编写一个显式的配置。Spring Boot会发现我们的配置,随后降低自动配置的优先级,以我们的配置为准。想弄明白这是如何实现的,让我们揭开Spring Boot自动配置的神秘面纱,看看它是如何运作的,以及它是怎么允许自己被覆盖的。

三、揭开自动配置的神秘面纱

Spring Boot自动配置自带了很多配置类,每一个都能运用在我们的应用程序里。它们都使用了Spring 4.0的条件化配置,可以在运行时判断这个配置是该被运用,还是该被忽略。大部分情况下,@ConditionalOnMissingBean 注解是覆盖自动配置的关键。
Spring Boot的 DataSourceAutoConfiguration 中定义的 JdbcTemplate Bean就是一个非常简
单的例子,演示了 @ConditionalOnMissingBean 如何工作:

@ConditionalOnMissingBean(JdbcOperations.class)
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(this.dataSource);
}

jdbcTemplate() 方法上添加了 @Bean 注解,在需要时可以配置出一个 JdbcTemplate Bean。但它上面还加了 @ConditionalOnMissingBean 注解,要求当前不存在 JdbcOperations类型( JdbcTemplate 实现了该接口)的Bean时才生效。如果当前已经有一个 JdbcOperations Bean了,条件即不满足,不会执行 jdbcTemplate() 方法。
什么情况下会存在一个 JdbcOperations Bean呢?Spring Boot的设计是加载应用级配置,随
后再考虑自动配置类。因此,如果我们已经配置了一个 JdbcTemplate Bean,那么在执行自动配置时就已经存在一个 JdbcOperations 类型的Bean了,于是忽略自动配置的 JdbcTemplate Bean。
关于Spring Security,自动配置会考虑几个配置类。在这里就不一一讨论每个配置类的细节,但覆盖Spring Boot自动配置的安全配置时,最重要的一个类是 SpringBootWebSecurity-Configuration 。以下是其中的一个代码片段:

@EnableConfigurationProperties
@ConditionalOnClass({ EnableWebSecurity.class })
@ConditionalOnMissingBean(WebSecurityConfiguration.class)
@ConditionalOnWebApplication
public class SpringBootWebSecurityConfiguration {
...
}

SpringBootWebSecurityConfiguration 上加了好几个注解。看到 @Condi-tionalOnClass 注解后,你就应该知道Classpath里必须要有 @EnableWebSecurity 注解。 @ConditionalOnWebApplication 说 明 这 必 须 是 个 Web 应 用 程 序 。 @ConditionalOn-
MissingBean 注解才是我们的安全配置类代替 SpringBootWebSecurityConfiguration 的关键所在。
@ConditionalOnMissingBean 注解要求当下没有 WebSecurityConfiguration 类型的Bean。虽然表面上我们并没有这么一个Bean,但通过在 SecurityConfig 上添加 @EnableWeb-Security 注解,我们实际上间接创建了一个 WebSecurityConfiguration Bean。所以在自动配置时,这个Bean就已经存在了, @ConditionalOnMissingBean 条件不成立, SpringBoot-WebSecurityConfiguration 提供的配置就被跳过了。
虽然Spring Boot的自动配置和 @ConditionalOnMissingBean 让我们能显式地覆盖那些可以自动配置的Bean,但并不是每次都要做到这种程度。下一篇文章让我们来看看怎么通过设置几个简单的配置属性调整自动配置组件吧。

相关文章
|
1月前
|
Java 开发者 微服务
手写模拟Spring Boot自动配置功能
【11月更文挑战第19天】随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。
50 0
|
2月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
58 4
|
2月前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
44 0
|
5天前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
43 14
|
27天前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
43 1
SpringBoot入门(7)- 配置热部署devtools工具
|
1月前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
43 2
 SpringBoot入门(7)- 配置热部署devtools工具
|
29天前
|
存储 前端开发 JavaScript
springboot中路径默认配置与重定向/转发所存在的域对象
Spring Boot 提供了简便的路径默认配置和强大的重定向/转发机制,通过合理使用这些功能,可以实现灵活的请求处理和数据传递。理解并掌握不同域对象的生命周期和使用场景,是构建高效、健壮 Web 应用的关键。通过上述详细介绍和示例,相信读者能够更好地应用这些知识,优化自己的 Spring Boot 应用。
30 3
|
1月前
|
Java 数据库连接
SpringBoot配置多数据源实战
第四届光学与机器视觉国际学术会议(ICOMV 2025) 2025 4th International Conference on Optics and Machine Vision
61 8
|
1月前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
63 9
|
1月前
|
Java 数据库连接 数据库
springboot启动配置文件-bootstrap.yml常用基本配置
以上是一些常用的基本配置项,在实际应用中可能会根据需求有所变化。通过合理配置 `bootstrap.yml`文件,可以确保应用程序在启动阶段加载正确的配置,并顺利启动运行。
122 2
下一篇
DataWorks