1、什么是SpringSecurity?
首先我们要知道SpringSecurity是Spring家族中的一员,是基于spring框架提供的一套web应用安全性的完整解决方案,包括可高度定制的认证、授权、鉴权等一系列的流程。
它在和springcloud进行整合时候具有其他的框架无法比拟的优势,因此逐渐成为微服务时代首选的安全框架。
除了SpringSecurity以外还有其他的框架也能够提供安全的支持,比如
2、springSecurity的整体架构

认证
AuthenticationManager
public interface AuthenticationManager {
Authentication authenticate(Authentication var1) throws AuthenticationException;
}
返回Authentication 表示认证成功,抛出AuthenticationException表示认证失败。它的实现类有几种

主要实现类是ProviderManager,它管理着很多AuthenticationPrividor 实例,SpringSecurity允许存在多个AuthenticationPrividor 用来实现多种认证方式。
Authentication Authentication类用来保存认证成功的用户的信息。
public interface Authentication extends Principal, Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
Object getCredentials();//获取用户凭证信息,一般指密码
Object getDetails();//获取用户详细信息
Object getPrincipal();//获取用户身份信息,用户名,用户对象等
boolean isAuthenticated();//用户是否认证成功
void setAuthenticated(boolean var1) throws IllegalArgumentException;
}
SecurityContextHolder维护用户信息SpringSecurity会将用户的认证信息保存在session中。SecurityContextHolder中维护了Authentication ,方便获取用户的信息。SecurityContextHolder中的数据保存是通过ThrealLocal来实现的,将用户的请求数据和当前处理用户请求的线程绑定在了一起。当用户登录完成之后就会清空SecurityContextHolder中的数据然后将用户的认证信息保存在session中,后面每当有请求过来的时候都会从session中取出用户的认证信息放到SecurityContextHolder中和当前线程绑定在一起,这样就可以实现在controller、service层都能够获取到用户的认证数据,当请求处理完成之后就会将认证信息放回session中然后删除SecurityContextHolder中的数据。
授权
AccessDecisionManager 访问决策管理器这个是用来判断这个请求是否允许被访问。接口源码如下:
public interface AccessDecisionManager {
void decide(Authentication var1, Object var2, Collection<ConfigAttribute> var3) throws AccessDeniedException, InsufficientAuthenticationException;
boolean supports(ConfigAttribute var1);
boolean supports(Class<?> var1);
}
AccessDecisionVoter访问决策投票器这个投票器会判断用户是否拥有访问该资源应有的角色,进而投出赞成、反对票或者弃权票。
public interface AccessDecisionVoter<S> {
int ACCESS_GRANTED = 1;
int ACCESS_ABSTAIN = 0;
int ACCESS_DENIED = -1;
boolean supports(ConfigAttribute var1);
boolean supports(Class<?> var1);
int vote(Authentication var1, S var2, Collection<ConfigAttribute> var3);
}
AccessDecisionManager 和AccessDecisionVoter都有众多的实现类,在AccessDecisionManager 中会遍历所有的AccessDecisionVoter进而判断用户是否拥有对应的访问权限。
ConfigAttribute用来保存授权时的角色信息当一个请求过来的时候AccessDecisionManager会将当前用户的角色封装成ConfigAttribute然后和AccessDecisionVoter进行遍历对比,如果投出了赞成票则用户对该资源有访问权限,否则没有访问权限,抛出异常。
public interface ConfigAttribute extends Serializable {
String getAttribute();
}
3、springSecurity环境搭建
搭建一个springboot项目编写接口

访问测试

然后加入我们的security的start依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
这个时候我们再启动项目

可以发现启动日志里面多了一条信息
Using generated security password: 40ea0442-79c3-4b2d-ae39-deeb27e3e279
然后我们继续访问刚才的接口

发现这里直接跳转到了登录页上面去,原来的接口已经无法直接访问到了。
然后我们登录,使用用户名user,密码40ea0442-79c3-4b2d-ae39-deeb27e3e279,这个就是刚才日志打印的uuid密码。然后就跳转到了正常的接口返回,这个时候访问其他的接口都可以实现访问。

4、springSecurity实现原理(官方文档)
以下图片来自官网
在架构上的实现是基于servlet容器中的过滤器来实现的。但是基于过滤器进行了一些封装。

DelegatingFilterProxy(委派过滤器代理类)就相当于是一个桥梁,连通servlet容器的生命周期和spring的ApplicationContext。官方大概的意思就是说提供了可以将servlet的过滤器使用springbean的方式来实现。

Spring Security的Servlet支持包含在FilterChainProxy中。FilterChainProxy是Spring Security提供的一种特殊过滤器,允许通过SecurityFilterChain委托给许多过滤器实例。由于FilterChainProxy是一个Bean,因此它通常包装在DelegatingFilterProxy中。

