Spring Security 应该是 Spring 全家桶中学习曲线最为陡峭的几个模块之一了,最开始看书学习的时候,在看了几回还有一些迷糊后就放弃了。html
直到前段时间再次捡起来,此次在网上找了不少资料后,终于对 Spring Security 有了必定的理解,发现,理解起来其实也不是那么难。前端
这里即是一个简单的梳理总结。java
不少人在刚开始学习 Web 应用程序的编写的时候,应该都使用过下面这种认证方式:web
这样的认证方式是很简单的,可是,Spring Security 中的认证流程又未尝不是这样的呢?只不过,Spring Security 经过更加统一的抽象接口实现了这样的认证流程。spring
前面的简单的认证流程中,是能够将一些东西抽象出来做为一个单独的实体,这些实体均可以在 Spring Security 中找到相应的对象,包括:数据库
用户输入的帐号密码等信息,这些东西其实就是用户的认证信息,对应到 Spring Security 中的话就是 Authentication
对象,只不过,Spring Security 中的 Authentication 对象除了保存用户的认证信息之外, 还能够用来保存用户认证成功后从数据库中拿到的用户的详细信息。后端
public interface Authentication extends Principal, Serializable {
Collection<? extends GrantedAuthority> getAuthorities(); // 用户权限
Object getCredentials(); // 用户认证信息
Object getDetails(); // 用户详细信息
Object getPrincipal(); // 用户身份信息
boolean isAuthenticated(); // 当前 Authentication 是否已认证
void setAuthenticated(boolean isAuthenticated);
}
复制代码
只凭用户提供的认证信息每每是不足以用来判断该用户是否合法的,所以,咱们一般还须要某种手段来获取保存在服务端的用户信息,同时,也须要某种手段来保存用户信息, 这些对应到 Spring Security 中的话就是 UserDetailsService
和 UserDetails
这两个对象。app
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}
复制代码
在拥有了用户提供的认证信息和保存在服务端的用户信息后,咱们就须要经过某种方式来比较这两份信息,而这种来效验用户认证信息的对象对应到 Spring Security 中即是 AuthenticationManager
对象了。ide
Authentication authenticate(Authentication authentication)throws AuthenticationException;
复制代码
而鉴于各类各样的用户认证信息和层出不穷的效验方式,Spring Security 提供了更易于咱们扩展的接口 AuthenticationProvider
和 ProviderManager
这个默认的 AuthenticationManager 实现。 使用时,咱们每每就只须要实现 AuthenticationProvider
就足够了。学习
public interface AuthenticationProvider {
Authentication authenticate(Authentication authentication) throws AuthenticationException;
boolean supports(Class<?> authentication);
}
复制代码
能够看到,AuthenticationProvider 中的方法 authenticate
会返回一个 Authentication
对象,当经过认证后,这个对象每每会保存用户的详细信息。
当用户的认证信息经过效验后,咱们每每还须要在服务端保存经过的认证信息或生成的令牌,这个保存经过的认证信息的对象在 Spring Security 中就是 SecurityContext
和 SecurityContextHolder
这两个对象, SecurityContext 保存已经过认证的 Authentication 对象,SecurityContextHolder 保存 SecurityContext 到当前线程的上下文,方便咱们的使用。
public interface SecurityContext extends Serializable {
Authentication getAuthentication();
void setAuthentication(Authentication authentication);
}
public class SecurityContextHolder {
public static SecurityContext getContext();
public void SecurityContext setContext();
}
复制代码
Spring Security 是基于 Filter 来实现的,而每一个请求每每也会分配一个线程,所以,Spring Security 在请求到达具体的处理逻辑以前,就能够在 Filter 中完成用户信息的认证,生成 SecurityContext 方面后续的使用。
这里在附上一张来源于 Spring Security(一) —— Architecture Overview | 芋道源码 —— 纯源码解析博客 的一张图,很好的解释了上述对象之间的关系:
能够看到,虽然 Spring Security 看似很复杂,可是其核心思想和之前那种简单的认证流程依然是同样的。只不过,Spring Security 将其中的关键部分抽象了处理,又提供了相应的扩展接口。
咱们在使用时,即可以实现本身的 UserDetailsService 和 UserDetails 来获取保存用户信息,实现本身的 Authentication 来保存特定的用户认证信息, 实现本身的 AuthenticationProvider 使用本身的 UserDetailsService 和 Authentication 来对用户认证信息进行效验。
固然了,Spring Security 还存在更多的功能,可是,在对基本流程有了必定的理解后,后续的内容也就可以更加容易的进行学习了。
其实除了 Spring Security 之外还看了一下 Spring Security OAuth2 和 Spring Security JWT,原本感受能够和这篇博客一块儿总结了,可是写着写着才发现,卧槽,Spring Security 部分的思路那么清晰, 怎么到了 Spring Security OAuth2 后就变得断断续续的。
而后才发信,只是大体的理清了 Spring Security 和 Spring Security OAuth2 之间的关系,细节上还有待推敲,所以,仍是留给之后吧 @_@