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,但并不是每次都要做到这种程度。下一篇文章让我们来看看怎么通过设置几个简单的配置属性调整自动配置组件吧。

相关文章
|
2月前
|
Java Spring
Spring Boot配置的优先级?
在Spring Boot项目中,配置可通过配置文件和外部配置实现。支持的配置文件包括application.properties、application.yml和application.yaml,优先级依次降低。外部配置常用方式有Java系统属性(如-Dserver.port=9001)和命令行参数(如--server.port=10010),其中命令行参数优先级高于系统属性。整体优先级顺序为:命令行参数 &gt; Java系统属性 &gt; application.properties &gt; application.yml &gt; application.yaml。
362 0
|
30天前
|
安全 算法 Java
在Spring Boot中应用Jasypt以加密配置信息。
通过以上步骤,可以在Spring Boot应用中有效地利用Jasypt对配置信息进行加密,这样即使配置文件被泄露,其中的敏感信息也不会直接暴露给攻击者。这是一种在不牺牲操作复杂度的情况下提升应用安全性的简便方法。
395 10
|
6月前
|
缓存 Java API
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的配置
本文介绍了在Spring Boot中配置Swagger2的方法。通过创建一个配置类,添加`@Configuration`和`@EnableSwagger2`注解,使用Docket对象定义API文档的详细信息,包括标题、描述、版本和包路径等。配置完成后,访问`localhost:8080/swagger-ui.html`即可查看接口文档。文中还提示了可能因浏览器缓存导致的问题及解决方法。
575 0
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的配置
|
6月前
|
监控 Java 应用服务中间件
微服务——SpringBoot使用归纳——为什么学习Spring Boot
本文主要探讨为什么学习Spring Boot。从Spring官方定位来看,Spring Boot旨在快速启动和运行项目,简化配置与编码。其优点包括:1) 良好的基因,继承了Spring框架的优点;2) 简化编码,通过starter依赖减少手动配置;3) 简化配置,采用Java Config方式替代繁琐的XML配置;4) 简化部署,内嵌Tomcat支持一键式启动;5) 简化监控,提供运行期性能参数获取功能。此外,从未来发展趋势看,微服务架构逐渐成为主流,而Spring Boot作为官方推荐技术,与Spring Cloud配合使用,将成为未来发展的重要方向。
178 0
微服务——SpringBoot使用归纳——为什么学习Spring Boot
|
6月前
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——Spring Boot 事务配置
本文介绍了 Spring Boot 中的事务配置与使用方法。首先需要导入 MySQL 依赖,Spring Boot 会自动注入 `DataSourceTransactionManager`,无需额外配置即可通过 `@Transactional` 注解实现事务管理。接着通过创建一个用户插入功能的示例,展示了如何在 Service 层手动抛出异常以测试事务回滚机制。测试结果表明,数据库中未新增记录,证明事务已成功回滚。此过程简单高效,适合日常开发需求。
746 0
|
6月前
|
Java 测试技术 微服务
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——少量配置信息的情形
本课主要讲解Spring Boot项目中的属性配置方法。在实际开发中,测试与生产环境的配置往往不同,因此不应将配置信息硬编码在代码中,而应使用配置文件管理,如`application.yml`。例如,在微服务架构下,可通过配置文件设置调用其他服务的地址(如订单服务端口8002),并利用`@Value`注解在代码中读取这些配置值。这种方式使项目更灵活,便于后续修改和维护。
84 0
|
6月前
|
SQL Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— application.yml 中对日志的配置
在 Spring Boot 项目中,`application.yml` 文件用于配置日志。通过 `logging.config` 指定日志配置文件(如 `logback.xml`),实现日志详细设置。`logging.level` 可定义包的日志输出级别,例如将 `com.itcodai.course03.dao` 包设为 `trace` 级别,便于开发时查看 SQL 操作。日志级别从高到低为 ERROR、WARN、INFO、DEBUG,生产环境建议调整为较高级别以减少日志量。本课程采用 yml 格式,因其层次清晰,但需注意格式要求。
519 0
|
2月前
|
人工智能 安全 Java
Spring Boot yml 配置敏感信息加密
本文介绍了如何在 Spring Boot 项目中使用 Jasypt 实现配置文件加密,包含添加依赖、配置密钥、生成加密值、在配置中使用加密值及验证步骤,并提供了注意事项,确保敏感信息的安全管理。
601 1
|
5月前
|
Java Spring
Spring框架的学习与应用
总的来说,Spring框架是Java开发中的一把强大的工具。通过理解其核心概念,通过实践来学习和掌握,你可以充分利用Spring框架的强大功能,提高你的开发效率和代码质量。
137 20
|
7月前
|
Cloud Native Java Nacos
springcloud/springboot集成NACOS 做注册和配置中心以及nacos源码分析
通过本文,我们详细介绍了如何在 Spring Cloud 和 Spring Boot 中集成 Nacos 进行服务注册和配置管理,并对 Nacos 的源码进行了初步分析。Nacos 作为一个强大的服务注册和配置管理平台,为微服务架构提供
2528 14