前言
自定义配置一章里主要讲解了:
- 覆盖Spring Boot自动配置
- 通过属性文件外置配置
- 定制应用程序错误页面
解析书中内容:
针对覆盖Spring Boot自动配置小节,作者的意思我们在装配Bean时,不要刻意去修改自动装配Bean,除非我们项目中有需要而去实施,针对安全也特别去阐明了SpringBoot自动配置会让应用程序的安全工作变得易如反掌,只需要在MAVEN构建的项目中添加如下引用:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
创建自定义的安全配置
覆盖自动配置,就是我们自己定义,直接显式地写一段配置,下面创建一个非常基础的Spring Security配置,目的主要是通过自定义的安全配置类,让我们的项目SpringBoot跳过了安全自动配置,从而使用我们的配置的安全配置:
package com.zcw.demo;
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;
/**
* @ClassName : SecurityConfig
* @Description : 覆盖自动配置的显示安全配置
* @Author : Zhaocunwei
* @Date: 2020-04-27 14:08
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ReaderRepository readerRepository;
@Override
protected void configure(HttpSecurity http) throws Exception{
http.authorizeRequests()
.antMatchers("/")
//要求登录这有READER角色
.access("hasRole('READER')")
.antMatchers("/**")
.permitAll()
.and()
.formLogin()
//设置登录表单的路径
.loginPage("/login")
.failureUrl("/login?error=true");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.userDetailsService(new UserDetailsService(){
//定义:自定义UserDetailsService
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return readerRepository.findOne(username);
}
});
}
}
通过demo我们知道它扩展了WebSecurityConfigurerAdapter的配置类,覆盖了两个不同的configure()方法,在SecurityConfig里,第一个configure()方法指明“/”-------ReadingListController的方法映射到了该路径的请求只有经过身份认证且拥有READER角色的用户才能访问。
通过这个配置我们在实际的项目中,可以拓展这个方法,限制不同的角色,访问不同的路径。
第二configure()方法
书中已经告诉我们设置了一个自定义的UserDetailsService,这个服务可以是任意实现了UserDetailsService的类,用于查找指定的用户名的用户。
【标红:告诉我们可以自定义一个类,然后直接实现这个接口就可以了】
创建匿名内部类
package com.zcw.demo;
import org.springframework.data.jpa.repository.JpaRepository;
import java.io.Reader;
/**
* @ClassName : ReaderRepository
* @Description : 用来持久化读者信息的仓库接口
* @Author : Zhaocunwei
* @Date: 2020-04-27 14:11
*/
public interface ReaderRepository extends JpaRepository<Reader,String> {
}
创建实体类:
package com.zcw.demo;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.util.Collection;
/**
* @ClassName : Reader
* @Description : 定义Reader的JPA实体
* @Author : Zhaocunwei
* @Date: 2020-04-27 16:21
*/
@Entity
@Data
public class Reader implements UserDetails {
@Id
private String username;
private String fullname;
private String password;
//授予REAER权限
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return null;
}
@Override
public String getUsername() {
return null;
}
//---------------不过期,不加锁,不禁用----------
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
//------------------------------------------
注意:
我们在上面的demo里面看到了,这个类已经实现了UserDetails接口以及其中的方法,表示这个类能代表Spring Security里的用户了,
@ConditionalOnMissingBean
@Bean
@ConditionalOnMissingBean(JdbcOperations.class)
public JdbcTemplate jdbcTemplate(){
return new JdbcTemplate(this.dataSource);
}
- 解释:
要求当前不存在JdbcOperations类型(JdbcTemplate实现了该接口)的Bean时才生效,如果当前已经有一个JdbcOperations Bean了,条件既不满足,不会执行jdbcTemplate()方法。
通过属性文件外置配置
一下是按照优先级排序,任何在高优先级属性员里设置的属性都会覆盖低优先级的相同属性,
- 命令行参数
- java:comp/env里的JNDI属性
- JVM系统属性
- 操作系统环境变量
- 随机生成的带random.* 前缀的属性(在设置其他属性时,可以引用他们,比如${random.long})
- 应用程序以外的application.properties或者application.yml文件
- 打包在应用程序内的application.properties或者 application.yml文件
- 通过 @PropertySource标注的属性源
- 默认属性
application.properties和application.yml文件的位置及优先级
(1)外置,在相对于应用程序运行目录的/config子目录里。
(2)外置,在应用程序运行的目录里。
(3)内置,在config包内
(4)内置,在Classpath根目录里
注意一点,在/config子目录里的application.properties会覆盖应用程序Classpath里的application.properties中的相同属性。
其实在实际的开发中,我们分为不同的环境,开发、测试、预上线、生产,这些环境我们可以把配置文件单独进行配置,不用每次进行构建jar包时,单独去修改我们的配置文件,这样构建完jar包以后,可以直接跟jar包放到同一级目录下,进行运行就可以了。
自动配置微调
书中只是针对我们的模块进行说明了,模块的缓存禁用与使用,每次运行时禁用缓存的配置:
spring:
thymeleaf:
cache: false
配置日志
针对日志配置,我还是通过书上介绍原来SpringBoot默认会使用Logback来记录日志,并用INFO级别输出到控制台,简略展示一下书中日志的配置文件:
logging:
level:
root: WARN
org:
springframework:
security: DEBUG
日志输出到指定的文件里面:(默认是10MB时会切分一次)
logging:
path: /var/logs/
file: zcw.log
level:
root: WARN
org:
springframework:
security: DEBUG
开始配置属性
针对配置属性这一阶段,我明白了原来我们在创建springboot项目时如果在类上添加@ConfigurationProperties注解,Spring Boot 自动配置会帮我们添加@EnableConfigurationProperties注解,同时他也会自动把驼峰规则的属性和使用连字符或下划线的同名属性关联起来
总结:
通过本章学习提升了对自定义配置的了解,同时知道了一个重要的信息是,SpringBoot 自动配置的安全配置时,最主要的一个类是SpringBootWebSecurityConfiguration,同时学习本章内容感觉自己之前只是简单的会用,而没有深入探究其中原委,其实本章文章特别基础的介绍了,我们怎么配置类,还有添加日志文件,及错误页面的配置,属性的加载,