前倾摘要
Spring 系列先写到这里,后面还会陆续更新,最近用到了Spring Security,先记录一下。
重点标识
Spring Security 整体架构入门,以及过滤器链。
核心功能
Spring Security认证,提供了多种认证方式,以及自定义认证方式。
我们先创建一个Spring Boot项目,引入web和Spring Security依赖:
重点是它提供了一个Authentication,提供了认证信息,用户信息,交给AuthenticationManager管理,也就是说,在AuthenticationManager里面,可以获取到用户的一些信息,如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
随便写一个接口,如此,运行项目访问,这个接口就已经被保护起来了:
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "hello";
}
}
这里,默认的用户名是user,密码则是启动日中,随机生成的一串字符:如图:
使用这个密码进行登录,就可以访问到被保护的接口了。
在Spring Security中所有的安全认证,都是基于过滤器实现的,如下,我们可以看到,Spring Boot启动后,所执行的关于Security的过滤器。
将这部分过滤器copy下来,我们可以看到
[org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@12a2585b, org.springframework.security.web.context.SecurityContextPersistenceFilter@30893e08, org.springframework.security.web.header.HeaderWriterFilter@6bee793f, org.springframework.security.web.csrf.CsrfFilter@7f973a14, org.springframework.security.web.authentication.logout.LogoutFilter@76e9f00b, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@68699afc, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@40d23c82, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@21b6c9c2, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@3b2553d9, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@4548d254, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@590f0c50, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@309cedb6, org.springframework.security.web.session.SessionManagementFilter@43b5021c, org.springframework.security.web.access.ExceptionTranslationFilter@36920bd6, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@45adc393]
一共有这么多过滤器,为我们进行各种的防护措施,安全认证,而这些,都是你使用了Spring security后,自带的,就比如说,我们默认的登陆页面,就是在DefaultLoginPageGeneratingFilter,注销页面,则是在DefaultLogoutPageGeneratingFilter里面。
而且,这些过滤并不是一个个注册到web.xml中的原生过滤器,而是统一由FilterChainProxy,管理,然后将FilterChainProxy放到web.xml中,这样无疑是方便了我们对过滤器进行管理。
甚至我们可以定制化,根据拦截不同请求,走不同过滤器,应用场景也一下子大大增加了。
那如果,不想让框架自动生成密码呢,在还没有使用数据库的情况下,我们可以这样配置,在properties或者yml中
spring.security.user.name=admin
spring.security.user.password=123456
那为什么可以这样呢,主要我们看一下security提供的UserDetails这个接口,我们以后自定义用户登录,连接数据库也能用到它。
public interface UserDetails extends Serializable {
//获取当前用户的认证信息
Collection<? extends GrantedAuthority> getAuthorities();
//获取用户密码
String getPassword();
//获取用户名
String getUsername();
//当前账户是否未未过期
boolean isAccountNonExpired();
//当前账户是否未锁定
boolean isAccountNonLocked();
//用户凭证是否未过期
boolean isCredentialsNonExpired();
//是否可用
boolean isEnabled();
}
这个就相当于规范一样,我们自己使用的时候,直接实现就好了。
那我们一开始看到的登录页面,默认的用户名和密码从哪来的呢,就是在UserDetailsServiceAutoConfiguration这个类里面:
我们可以看到,这里的User实际上,就是在InMemoryUserDetailsManager这个方法中的 SecurityProperties.User user = properties.getUser();这里面,再进入一层,我们可以看到如下:
用户名默认就是user,密码默认则是UUID了。
而且,我们可以看到,这个类:
@ConfigurationProperties(
prefix = "spring.security"
)
public class SecurityProperties {
就是我们在properties里面的配置头,不过在这里,我们只能配置一个用户,如果我们有多个用户,那我们可以在代码中这样配置。
{noop},就是不加密的意思!
@Configuration
public class SecurityConfig {
@Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager() {
return new InMemoryUserDetailsManager(
User.withUsername("admin").password("{noop}123").roles().build()
,User.withUsername("user").password("{noop}123").roles().build());
}
}