文章目录
- 基本原理
- Authentication接口
- UserDetailsService 接口
- PasswordEncoder 接口
基本原理
SpringSecurity 本质是一个过滤器链,采用的是责任链设计模式。
- 启动的时候,控制台打印出来的 DefaultSecurityFilterChain 过滤器:
org.springframework.security.web.session.DisableEncodeUrlFilter@2c9a6717,
org.springframework.security.web.session.ForceEagerSessionCreationFilter@7b3cde6f,
org.springframework.security.web.session.ForceEagerSessionCreationFilter@506aabf6,
// 将 Security 上下文与 Spring Web 中用于处理异步请求映射的 WebAsyncManager 进行集成。
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@6d091cad,
// 在每次请求处理之前将该请求相关的安全上下文信息加载到 SecurityContextHolder 中,然后在该次请求处理完成之后,将SecurityContextHolder
// 中关于这次请求的信息存储到一个“仓储”中,然后将SecurityContextHolder 中的信息清除,例如在 Session 中维护一个用户的安全信息就是这个过滤
// 器处理的。
org.springframework.security.web.context.SecurityContextPersistenceFilter@5cbd94b2,
// 用于将头信息加入响应中。
org.springframework.security.web.header.HeaderWriterFilter@3330f3ad,
// 用于处理退出登录。
org.springframework.security.web.authentication.logout.LogoutFilter@24a2e565,
// 自定义过滤器
com.tyr.security.support.authentication.sms.SmsCodeAuthenticationFilter@7c663eaf,
// 对 /login 的 POST 请求做拦截,校验表单中用户名,密码。
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@12a2585b,
// 自定义过滤器
com.tyr.security.support.authentication.jwt.JwtAuthenticationFilter@3bb5ceb,
// 自定义过滤器
com.tyr.security.support.authentication.mail.MailAuthenticationFilter@1e692555,
// 用来处理请求的缓存。
org.springframework.security.web.savedrequest.RequestCacheAwareFilter@6824b913,
// 主要是包装请求对象 request。
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@756aadfc,
// 当用户没有登录而直接访问资源时, 从 cookie 里找出用户的信息, 如果 Spring Security 能够识别出用户提供的 remember me cookie,
// 用户将不必填写用户名和密码, 而是直接登录进入系统,该过滤器默认不开启。
org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter@3b95a6db,
// 检测 SecurityContextHolder 中是否存在Authentication 对象,如果不存在为其提供一个匿名 Authentication。
org.springframework.security.web.authentication.AnonymousAuthenticationFilter@3ba0ae41,
// 管理 session 的过滤器
org.springframework.security.web.session.SessionManagementFilter@f425231,
// 异常过滤器,用来处理在认证授权过程中抛出的异常
org.springframework.security.web.access.ExceptionTranslationFilter@b46e103,
// 一个方法级的权限过滤器, 基本位于过滤链的最底部。
org.springframework.security.web.access.intercept.FilterSecurityInterceptor@3a2e9f5b
- Spring Security 采取过滤链实现认证与授权,只有当前过滤器通过,才能进入下一个过滤器。
- 绿色部分是认证过滤器,需要我们自己配置,可以配置多个认证过滤器。认证过滤器可以使用 Spring Security 提供的认证过滤器,也可以自定义过滤器(例如:邮箱,短信验证等)。认证过滤器要在 configure(HttpSecurity http)方法中配置,没有配置不生效。
Authentication接口
principal
- 要进行身份验证的主体的身份。对于带有用户名和密码的身份验证请求,这将是用户名。调用方应填充身份验证请求的主体。
- AuthenticationManager 实现通常会返回包含更丰富信息的身份验证作为应用程序使用的主体。许多身份验证提供程序将创建一个UserDetails对象作为主体。
credentials
- 证明主体正确的凭据。这通常是一个密码,但可以是与 相关的 AuthenticationManager任何内容。调用方应填充凭据。
details
- 存储有关身份验证请求的其他详细信息。这些可能是 IP 地址、证书序列号等。
- 有关身份验证请求的其他详细信息,如果未使用,则为 null 。
authorities
- 已授予委托人的权限。
- 实现应确保对返回的集合数组的修改不会影响 Authentication 对象的状态,或使用不可修改的实例。
- 授予主体的权限,或空集合(如果令牌尚未经过身份验证),从不为null。
authenticated
- 令牌是否已经通过认证。
- true:令牌应该被信任 或 false:令牌不应该被信任。
UserDetailsService 接口
- 当什么也没有配置的时候,账号和密码是由 Spring Security 定义生成的。而在实际项目中账号和密码都是从数据库中查询出来的。 所以我们要通过自定义逻辑控制认证逻辑。
- 如果需要自定义逻辑时,只需要实现 UserDetailsService 接口即可。
public interface UserDetailsService {/**根据用户名定位用户。在实际实现中,搜索可能区分大小写或不区分大小写,具体取决于实现实例的配置方式。在这种情况下, UserDetails 返回的 对象可能具有与实际请求的用户名不同的大小写。形参:username – 标识需要其数据的用户的用户名。返回值:完全填充的用户记录(从不 null)抛出:UsernameNotFoundException – 如果找不到用户或用户没有授权*/// UserDetails 系统默认的用户主体UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;}
UserDetails
public interface UserDetails extends Serializable {// 表示获取登录用户所有权限Collection<? extends GrantedAuthority> getAuthorities();String getPassword();String getUsername();// 表示判断账户是否过期boolean isAccountNonExpired();// 表示判断账户是否被锁定boolean isAccountNonLocked();// 表示凭证{密码}是否过期boolean isCredentialsNonExpired();// 表示当前用户是否可用boolean isEnabled();
}
PasswordEncoder 接口
/*** Service interface for encoding passwords.** The preferred implementation is {@code BCryptPasswordEncoder}.** @author Keith Donald*/
public interface PasswordEncoder {// 表示把参数按照特定的解析规则进行解析String encode(CharSequence rawPassword);// 表示验证从存储中获取的编码密码与编码后提交的原始密码是否匹配。如果密码匹配,则返回 true;如果不匹配,则返回 false。// 第一个参数表示需要被解析的密码。第二个参数表示存储的密码。boolean matches(CharSequence rawPassword, String encodedPassword);// 表示如果解析的密码能够再次进行解析且达到更安全的结果则返回 true,否则返回false。默认返回 false。default boolean upgradeEncoding(String encodedPassword) {return false;}}
你知道的越多,你不知道的越多。