我觉得我懂了系列之SpringSecurity(上)

  • 权限设计

对于一个完善的系统,使用会有不少人使用:最起码也会包含用户端和后台管理端两个角色,固然随着业务不断复杂,确定会产生更多的角色,这些角色被赋予不一样的权限,只能操做系统中的某一部分功能,而后全部角色一块儿来操做各自的模块,整个系统才能处于一个正常的活跃状态。 对于一个系统的登陆方式,从帐号密码登陆,邮箱密码登录,到很是方便的第三方登陆方式:好比掘金的第三方登陆就使用了:微信、GitHub、微博。应该是能够更加方便的引流吧,去除繁琐的注册流程。 除此以外,登陆系统的设计还包含在一个分布式系统中的单点登陆SSO,使用CAS进行处理,还有jwt等等这些均可以集成在SpringSecurity中,最近连续看了好几天的Security源码(以前粗略的看过一遍,基本没理解),发现好复杂啊,好绕,功能强大势必会致使复杂的配置,因此在有些场景下使用就会觉着,可是权限设计又是每个系统都须要的,因此决定在这里仔细缕一缕。html

  • Spring Security 源码访问认证流程分析

从listener-filter-servlet中的filter提及,security的入口实际上是filter的FilterChain中的一个filter。java

FilterChain: is an object provided by the servlet container to the developer giving a view into the invocation chain of a filtered request for a resource.Filters use the FilterChain to invoke the next filter in the chain, or if the calling filter is the last filter in the chain, to invoke the resource at the end of the chain.react

ApplicationFilterChain: Implementation of FilterChain used to manage the execution of a set of filters for a particular request. When the set of defined filters has all beenexecuted, the next call to doFilter() will execute the servlet's service() method itself.web

先来看一下通常都有哪些filter,以下图所示,其中有些是我引入Actuator监控模块加入的,先不要care,下次单独说一下他是干吗的spring

其中有个filter:DelegatingFilterProxy,这是一个代理,那么代理的是谁呢?内部持有的FilterChainProxy,它作该过滤器应该作的事情,那么这个过滤器干吗了呢?咱们须要了解一个FilterChainProxy这个类(👇),这个就是咱们要security的入口,而后下面咱们从这个入口开始一点一点的分析。express

FilterChainProxy 介绍安全

SecurityFilterChain 介绍微信

首先,在上面介绍中说到filterChainProxy内部的List<SecurityFilterChain> filterChains,须要从这个过滤器链的集合中匹配出当前请求的那个过滤器链,有个关键:RequestMatcher(👇),而后从将匹配到的securityFilterChain中的filter集合拿出来,便开始了进行了过滤,以下图所示分布式

RequestMatcher 介绍ide

经过下图看下这些默认过滤器的功能,没有详细看过,后续再谈:

咱们着重分析一下: UsernamePasswordAuthenticationFilter这个类就是验证的关键, 第一步:调用父抽象类的doFilter方法:

第二步:调用子类实现的attemptAuthentication方法:

第三步:认证开始: 抽象接口:AuthenticationManager,方法:authenticate(Authentication authentication) 一般使用实现 ProviderManager,它持有一个List providers,这些provider提供了不一样的认证方式,能够自定义 AuthenticationProvider进行认证

咱们来看一下这些authenticationProvider都是干吗的

DaoAuthenticationProvider:数据访问认证方式,也就是说能够从不一样的数据源来进行认证, 从上图中也能够看到父类 AbstractUserDetailsAuthenticationProvider,提供入口authenticate()方法, 而后定义一些抽象方法,子类去实现具体的逻辑,又是模板模式的体现,在 DaoAuthenticationProvider中有个很重要的属性: UserDetailsService,则会个接口里面只有一个方法: loadUserByUsername,而后不一样的服务能够采起不一样的策略来实现,对,这里我感受就是一个策略模式,

  • Spring Security 源码访问受权流程分析

FilterSecurityInterceptor 感受也很绕,须要看下那个投票究竟是干吗的, 核心:invoke()方法

beforeInvocation()主要流程:

this.accessDecisionManager.decide(authenticated, object, attributes);
//主要是基于AccessDecisionVoter的一个投票过程
//在已经确保用户经过了认证,如今基于登陆的当前用户信息,和目标资源的安全配置属性
//进行相应的权限检查,若是检查失败,则抛出相应的异常 AccessDeniedException
复制代码

投票的的经过策略:

  • 1.AffirmativeBased-任意1个经过受权成功 Simple concrete implementation of AccessDecisionManager that grants access if any AccessDecisionVoter returns an affirmative response.
  • 2.ConsensusBased-部分经过受权成功 "Consensus" here means majority-rule (ignoring abstains) rather than unanimous agreement (ignoring abstains).
  • 3.UnanimousBased-所有经过受权成功 Simple concrete implementation of AccessDecisionManager that requires all voters to abstain or grant access. 扩展点:
    1. securityMetadataSource 获取安全的元数据(初始化的时候将咱们的配置加载进去)
    1. AccessDecisionManager
    1. AccessDecisionVoter 涉及到各类expressionHandle进行match决定投出什么样的票
  • Spring Security 初始化分析(配置如何生效,如何配置)

对于SpringBoot项目进行分析,使用SpringBoot以后最强大的功能即是自动配置,引入security的stater以后,什么都不用干,访问咱们的以前的controller接口,就发现已经被保护起来,缘由就是这些自动引入的以及经过它们又间接引入的配置:

org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityRequestMatcherProviderAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
复制代码

说一个主要的自动配置:

而后再上图最右边开始里面开始加载webSecurity等一系列的配置; 接下来咱们先来分析一下security配置涉及的组件, 咱们从SecurityBuilder提及,看到这个想到是一个建造者模式,这是一个高度抽象的接口:

/** * Interface for building an Object * @param <O> The type of the Object being built */
public interface SecurityBuilder<O> {
	/** * Builds the object and returns it or null. * @return the Object to be built or null if the implementation allows it. * @throws Exception if an error occurred when building the Object */
	O build() throws Exception;
}
复制代码

继承实现:

build的统一模板流程:

再看一下 SecurityConfigurer:

/** * Allows for configuring a {@link SecurityBuilder}. All {@link SecurityConfigurer} first * have their {@link #init(SecurityBuilder)} method invoked. After all * {@link #init(SecurityBuilder)} methods have been invoked, each * {@link #configure(SecurityBuilder)} method is invoked. * @param <O> The object being built by the {@link SecurityBuilder} * @param <B> The {@link SecurityBuilder} that builds objects of type O. This is also the * {@link SecurityBuilder} that is being configured. */
public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {
	/** * Initialize the {@link SecurityBuilder}. Here only shared state should be created * and modified, but not properties on the {@link SecurityBuilder} used for building * the object. This ensures that the {@link #configure(SecurityBuilder)} method uses * the correct shared objects when building. * @param builder * @throws Exception */
	void init(B builder) throws Exception;
	/** * Configure the {@link SecurityBuilder} by setting the necessary properties on the * {@link SecurityBuilder}. * @param builder * @throws Exception */
	void configure(B builder) throws Exception;
}
复制代码

继承实现:

SecurityBuilder 是用来构建 O这个类型的对象的; SecurityConfigurer 是用来对不一样的build过程当中的属性进行配置; 这里面包含有众多的类,咱们说一些重要的:

  • HttpSecurity:建立的对象类型为DefaultSecurityFilterChain
  • WebSecurity:create the FilterChainProxy known as the Spring Security Filter Chain (springSecurityFilterChain).
  • WebSecurityConfigurer:Allows customization to the {@link WebSecurity}.
  • WebSecurityConfigurerAdapter:Provides a convenient base class for creating a WebSecurityConfigurer instance.
  • DefaultSecurityFilterChain:是SecurityFilterChain的默认实现,提供两个功能:url匹配filter集合处理,在springSecurityFilterChain中能够建立一个或者多个SecurityFilterChain,而且根据SecurityFilterChain提供的requestMatcher来决定使用哪一个SecurityFilterChain中的filter来处理当前请求,至关于于一个代理; httpSecurity的构建过程:

固然,还差了不少内容:如何配置,自定义拓展,cas,jwt,第三方登陆等,我觉着这些东西,第一是知道一些使用规范流程,好比:cas单点登陆的流程,Oauth2.0的流程,而后加上对整个security是如何进行初始化咱们的配置,如何进行认证和受权的流程的熟悉,将这些内容添加进来也就变得会容易一些,固然实际操做的过程当中确定会有各类问题,一个一个解决就完事了。

参考:

www.shangyang.me/categories/… www.jianshu.com/u/fb66b7412… zhuanlan.zhihu.com/c_111502114… docs.spring.io/spring-secu…

相关文章
相关标签/搜索