# 启用Spring Security
保护Spring应用的第一步就是将Spring Boot security starter依赖添加到构建文件中。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
只要添加了该依赖,当应用启动的时候,自动配置功能会探测到Spring Security出现在了类路径中,因此它就会初始化一些安全配置。这时,你可以尝试启动应用访问主页,应用会展示一个登录页面并提示你进行认证。用户名为user,密码会被写出应用的日志文件中。日志条目大致如下所示:
Using generated security password: 893043b6-a647-4f21-8787-70d25c6151a1
假设输入了正确的用户名和密码,你就有权限访问应用了。
通过将security 起步依赖添加到项目的构建文件中,我们得到了以下安全特性:
- 所有的HTTP请求路径都需要认证
- 不需要特定的角色和权限
- 系统只有一个用户,用户名为user
我们需要:
- 提供多个用户,并提供一个注册页面
-对不同的请求路径,执行不同的安全规则
# 配置Spring Security
基础安全配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
}
## 配置用户储存
Spring Security为配置用户储存提供了多个可选方案:
- 基于内存的用户存储
- 基于JDBC的用户存储
- 以LDAP作为后端的用户存储
- 自定义用户详情服务
不管使用那种用户存储,都可以通过覆盖WebSecurityConfigureAdapter基础配置类中定义的configure()方法进行配置。首先,我们可以将如下的方法添加到SecurityConfig类中:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
...
}
}
现在,我们需要使用指定的AuthenticationManagerBuilder替换上面的省略号。以此来定义在认证过程中如何查找用户。
## 基于用户内存的用户存储
用户信息可以存储在内存之中。假设我们只有数量有限的几个用户,而且这些用户几乎不会发生改变,将这些用户定义成安全配置的一部分是非常简单的。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
/*基于内存的用户存储*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("buzz")
.password(passwordEncoder().encode("123"))
.authorities("ROLE_USER");
}
}
AuthenticationManagerBuilder使用构造者(builder)风格的接口来构建认证环节。我们调用inMemoryAuthentication方法来指定用户信息。通过withUser()方法来配置用户而密码就是password,用户权限就是authorities方法。
需要注意的是,我们需要定义一个密码编码器,能够用正确方式解析密码。
## 基于JDBC的用户存储
用户信息通常会在关系型数据库中进行维护,基于JDBC的用户存储方案会更加合理一些。
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery(
"select username,password,enabled from Users "
+ "where username = ?"
)
.passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
DataSource dataSource;
@Autowired(required = false)
public SecurityConfig(DataSource dataSource) {
this.dataSource = dataSource;
}
在这里的configure实现中,调用了AuthenticationManagerBuilder的jdbcAuthentication方法,我们还必须设置一个DataSource,这样它才能知道如何访问数据库。这里的DataSource是通过自动装配的技巧获得的。
Spring Security内部源码,展现了当查找用户时所执行的SQL查询语句:
public static final String DEF_USERS_BY_USERNAME_QUERY =
"select username,password,enabled " +
"from users " +
"where username = ?";
public static final St