Spring Security 认证流程梳理

前言

Spring Security 应该是 Spring 全家桶中学习曲线最为陡峭的几个模块之一了,最开始看书学习的时候,在看了几回还有一些迷糊后就放弃了。html

直到前段时间再次捡起来,此次在网上找了不少资料后,终于对 Spring Security 有了必定的理解,发现,理解起来其实也不是那么难。前端

这里即是一个简单的梳理总结。java

简单的认证流程

不少人在刚开始学习 Web 应用程序的编写的时候,应该都使用过下面这种认证方式:web

  1. 前端页面获取到用户的帐号密码等信息后经过 POST 请求发送给后端
  2. 后端拿到用户的帐号密码等信息到数据库查询服务端保存的用户信息
  3. 对比数据库中的用户信息和前端传递过来的帐号密码信息
  4. 相同就生成一个 Token 保存到 Seesion 并将 Token 返回给客户端
  5. 前端保存拿到的 Token 后在后续的请求中携带这一 Token 来证实本身的身份

这样的认证方式是很简单的,可是,Spring Security 中的认证流程又未尝不是这样的呢?只不过,Spring Security 经过更加统一的抽象接口实现了这样的认证流程。spring

Spring Security

前面的简单的认证流程中,是能够将一些东西抽象出来做为一个单独的实体,这些实体均可以在 Spring Security 中找到相应的对象,包括:数据库

  1. 用户输入的帐号密码等信息,这些东西其实就是用户的认证信息,对应到 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);
    }
    复制代码
  2. 只凭用户提供的认证信息每每是不足以用来判断该用户是否合法的,所以,咱们一般还须要某种手段来获取保存在服务端的用户信息,同时,也须要某种手段来保存用户信息, 这些对应到 Spring Security 中的话就是 UserDetailsServiceUserDetails 这两个对象。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();
    }
    复制代码
  3. 在拥有了用户提供的认证信息和保存在服务端的用户信息后,咱们就须要经过某种方式来比较这两份信息,而这种来效验用户认证信息的对象对应到 Spring Security 中即是 AuthenticationManager 对象了。ide

    Authentication authenticate(Authentication authentication)throws AuthenticationException;
    复制代码

    而鉴于各类各样的用户认证信息和层出不穷的效验方式,Spring Security 提供了更易于咱们扩展的接口 AuthenticationProviderProviderManager 这个默认的 AuthenticationManager 实现。 使用时,咱们每每就只须要实现 AuthenticationProvider 就足够了。学习

    public interface AuthenticationProvider {
      Authentication authenticate(Authentication authentication) throws AuthenticationException;
      boolean supports(Class<?> authentication);
    }
    复制代码

    能够看到,AuthenticationProvider 中的方法 authenticate 会返回一个 Authentication 对象,当经过认证后,这个对象每每会保存用户的详细信息。

  4. 当用户的认证信息经过效验后,咱们每每还须要在服务端保存经过的认证信息或生成的令牌,这个保存经过的认证信息的对象在 Spring Security 中就是 SecurityContextSecurityContextHolder 这两个对象, 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 之间的关系,细节上还有待推敲,所以,仍是留给之后吧 @_@

参考连接

相关文章
相关标签/搜索