亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

HttpSecurity是什么

發布時間:2021-12-07 13:54:03 來源:億速云 閱讀:161 作者:iii 欄目:大數據

這篇文章主要介紹“HttpSecurity是什么”,在日常操作中,相信很多人在HttpSecurity是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”HttpSecurity是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

1.抽絲剝繭

首先我們來看下 HttpSecurity 的繼承關系圖:

HttpSecurity是什么  

可以看到,HttpSecurity 繼承自 AbstractConfiguredSecurityBuilder,同時實現了 SecurityBuilder 和 HttpSecurityBuilder 兩個接口。

我們來看下 HttpSecurity 的定義:

public final class HttpSecurity extends
  AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain, HttpSecurity>
  implements SecurityBuilder<DefaultSecurityFilterChain>,
  HttpSecurityBuilder<HttpSecurity> {
        //...
}
 

這里每一個類都帶有泛型,看得人有點眼花繚亂。

我把這個泛型類拿出來和大家講一下,小伙伴們就明白了。

泛型主要是兩個,DefaultSecurityFilterChain 和 HttpSecurity,HttpSecurity 就不用說了,這是我們今天的主角,那么 DefaultSecurityFilterChain 是干嘛的?

這我們就得從 SecurityFilterChain 說起了。

 

1.1 SecurityFilterChain

先來看定義:

public interface SecurityFilterChain {
 boolean matches(HttpServletRequest request);
 List<Filter> getFilters();
}
 

SecurityFilterChain 其實就是我們平時所說的 Spring Security 中的過濾器鏈,它里邊定義了兩個方法,一個是 matches 方法用來匹配請求,另外一個 getFilters 方法返回一個 List 集合,集合中放著 Filter 對象,當一個請求到來時,用 matches 方法去比較請求是否和當前鏈吻合,如果吻合,就返回 getFilters 方法中的過濾器,那么當前請求會逐個經過 List 集合中的過濾器。這

SecurityFilterChain 接口只有一個實現類,那就是 DefaultSecurityFilterChain:

public final class DefaultSecurityFilterChain implements SecurityFilterChain {
 private static final Log logger = LogFactory.getLog(DefaultSecurityFilterChain.class);
 private final RequestMatcher requestMatcher;
 private final List<Filter> filters;

 public DefaultSecurityFilterChain(RequestMatcher requestMatcher, Filter... filters) {
  this(requestMatcher, Arrays.asList(filters));
 }

 public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {
  logger.info("Creating filter chain: " + requestMatcher + ", " + filters);
  this.requestMatcher = requestMatcher;
  this.filters = new ArrayList<>(filters);
 }

 public RequestMatcher getRequestMatcher() {
  return requestMatcher;
 }

 public List<Filter> getFilters() {
  return filters;
 }

 public boolean matches(HttpServletRequest request) {
  return requestMatcher.matches(request);
 }

 @Override
 public String toString() {
  return "[ " + requestMatcher + ", " + filters + "]";
 }
}
 

DefaultSecurityFilterChain 只是對 SecurityFilterChain 中的方法進行了實現,并沒有特別值得說的地方,松哥也就不啰嗦了。

那么從上面的介紹中,大家可以看到,DefaultSecurityFilterChain 其實就相當于是 Spring Security 中的過濾器鏈,一個 DefaultSecurityFilterChain 代表一個過濾器鏈,如果系統中存在多個過濾器鏈,則會存在多個 DefaultSecurityFilterChain 對象。

接下來我們把 HttpSecurity 的這幾個父類捋一捋。

 

1.2 SecurityBuilder

public interface SecurityBuilder<O> {
 O build() throws Exception;
}
 

SecurityBuilder 就是用來構建過濾器鏈的,在 HttpSecurity 實現 SecurityBuilder 時,傳入的泛型就是 DefaultSecurityFilterChain,所以 SecurityBuilder#build 方法的功能很明確,就是用來構建一個過濾器鏈出來。

 

1.3 HttpSecurityBuilder

HttpSecurityBuilder 看名字就是用來構建 HttpSecurity 的。不過它也只是一個接口,具體的實現在 HttpSecurity 中,接口定義如下:

public interface HttpSecurityBuilder<H extends HttpSecurityBuilder<H>> extends
  SecurityBuilder<DefaultSecurityFilterChain> {
 <C extends SecurityConfigurer<DefaultSecurityFilterChain, H>> C getConfigurer(
   Class<C> clazz);
 <C extends SecurityConfigurer<DefaultSecurityFilterChain, H>> C removeConfigurer(
   Class<C> clazz);
 <C> void setSharedObject(Class<C> sharedType, C object);
 <C> C getSharedObject(Class<C> sharedType);
 H authenticationProvider(AuthenticationProvider authenticationProvider);
 H userDetailsService(UserDetailsService userDetailsService) throws Exception;
 H addFilterAfter(Filter filter, Class<? extends Filter> afterFilter);
 H addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter);
 H addFilter(Filter filter);
}
 

這里的方法比較簡單:

  1. getConfigurer 獲取一個配置對象。Spring Security 過濾器鏈中的所有過濾器對象都是由 xxxConfigure 來進行配置的,這里就是獲取這個 xxxConfigure 對象。
  2. removeConfigurer 移除一個配置對象。
  3. setSharedObject/getSharedObject 配置/獲取由多個 SecurityConfigurer 共享的對象。
  4. authenticationProvider 方法表示配置驗證器。
  5. userDetailsService 配置數據源接口。
  6. addFilterAfter 在某一個過濾器之前添加過濾器。
  7. addFilterBefore 在某一個過濾器之后添加過濾器。
  8. addFilter 添加一個過濾器,該過濾器必須是現有過濾器鏈中某一個過濾器或者其擴展。

這便是 HttpSecurityBuilder 中的功能,這些接口在 HttpSecurity 中都將得到實現。

 

1.4 AbstractSecurityBuilder

AbstractSecurityBuilder 類實現了 SecurityBuilder 接口,該類中主要做了一件事,就是確保整個構建只被構建一次。

public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {
 private AtomicBoolean building = new AtomicBoolean();
 private O object;
 public final O build() throws Exception {
  if (this.building.compareAndSet(false, true)) {
   this.object = doBuild();
   return this.object;
  }
  throw new AlreadyBuiltException("This object has already been built");
 }
 public final O getObject() {
  if (!this.building.get()) {
   throw new IllegalStateException("This object has not been built");
  }
  return this.object;
 }
 protected abstract O doBuild() throws Exception;
}
 

可以看到,這里重新定義了 build 方法,并設置 build 方法為 final 類型,無法被重寫,在 build 方法中,通過 AtomicBoolean 實現該方法只被調用一次。具體的構建邏輯則定義了新的抽象方法 doBuild,將來在實現類中通過 doBuild 方法定義構建邏輯。

 

1.5 AbstractConfiguredSecurityBuilder

AbstractSecurityBuilder 方法的實現類就是 AbstractConfiguredSecurityBuilder。

AbstractConfiguredSecurityBuilder 中所做的事情就比較多了,我們分別來看。

首先 AbstractConfiguredSecurityBuilder 中定義了一個枚舉類,將整個構建過程分為 5 種狀態,也可以理解為構建過程生命周期的五個階段,如下:

private enum BuildState {
 UNBUILT(0),
 INITIALIZING(1),
 CONFIGURING(2),
 BUILDING(3),
 BUILT(4);
 private final int order;
 BuildState(int order) {
  this.order = order;
 }
 public boolean isInitializing() {
  return INITIALIZING.order == order;
 }
 public boolean isConfigured() {
  return order >= CONFIGURING.order;
 }
}
 

五種狀態分別是 UNBUILT、INITIALIZING、CONFIGURING、BUILDING 以及 BUILT。另外還提供了兩個判斷方法,isInitializing 判斷是否正在初始化,isConfigured 表示是否已經配置完畢。

AbstractConfiguredSecurityBuilder 中的方法比較多,松哥在這里列出來兩個關鍵的方法和大家分析:

private <C extends SecurityConfigurer<O, B>> void add(C configurer) {
 Assert.notNull(configurer, "configurer cannot be null");
 Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer
   .getClass();
 synchronized (configurers) {
  if (buildState.isConfigured()) {
   throw new IllegalStateException("Cannot apply " + configurer
     + " to already built object");
  }
  List<SecurityConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.configurers
    .get(clazz) : null;
  if (configs == null) {
   configs = new ArrayList<>(1);
  }
  configs.add(configurer);
  this.configurers.put(clazz, configs);
  if (buildState.isInitializing()) {
   this.configurersAddedInInitializing.add(configurer);
  }
 }
}
private Collection<SecurityConfigurer<O, B>> getConfigurers() {
 List<SecurityConfigurer<O, B>> result = new ArrayList<>();
 for (List<SecurityConfigurer<O, B>> configs : this.configurers.values()) {
  result.addAll(configs);
 }
 return result;
}
 

第一個就是這個 add 方法,這相當于是在收集所有的配置類。將所有的 xxxConfigure 收集起來存儲到 configurers 中,將來再統一初始化并配置,configurers 本身是一個 LinkedHashMap ,key 是配置類的 class,value 是一個集合,集合里邊放著 xxxConfigure 配置類。當需要對這些配置類進行集中配置的時候,會通過 getConfigurers 方法獲取配置類,這個獲取過程就是把 LinkedHashMap 中的 value 拿出來,放到一個集合中返回。

另一個方法就是 doBuild 方法。

@Override
protected final O doBuild() throws Exception {
 synchronized (configurers) {
  buildState = BuildState.INITIALIZING;
  beforeInit();
  init();
  buildState = BuildState.CONFIGURING;
  beforeConfigure();
  configure();
  buildState = BuildState.BUILDING;
  O result = performBuild();
  buildState = BuildState.BUILT;
  return result;
 }
}
private void init() throws Exception {
 Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
 for (SecurityConfigurer<O, B> configurer : configurers) {
  configurer.init((B) this);
 }
 for (SecurityConfigurer<O, B> configurer : configurersAddedInInitializing) {
  configurer.init((B) this);
 }
}
private void configure() throws Exception {
 Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
 for (SecurityConfigurer<O, B> configurer : configurers) {
  configurer.configure((B) this);
 }
}
 

在 AbstractSecurityBuilder 類中,過濾器的構建被轉移到 doBuild 方法上面了,不過在 AbstractSecurityBuilder 中只是定義了抽象的 doBuild 方法,具體的實現在 AbstractConfiguredSecurityBuilder。

doBuild 方法就是一邊更新狀態,進行進行初始化。

beforeInit 是一個預留方法,沒有任何實現。

init 方法就是找到所有的 xxxConfigure,挨個調用其 init 方法進行初始化。

beforeConfigure 是一個預留方法,沒有任何實現。

configure 方法就是找到所有的 xxxConfigure,挨個調用其 configure 方法進行配置。

最后則是 performBuild 方法,是真正的過濾器鏈構建方法,但是在 AbstractConfiguredSecurityBuilder 中 performBuild 方法只是一個抽象方法,具體的實現在 HttpSecurity 中。

這便是 HttpSecurity 所有父類、父接口的功能。

看完了父輩,接下來回到我們今天文章的主題,HttpSecurity。

 

2. HttpSecurity

HttpSecurity 做的事情,就是進行各種各樣的 xxxConfigurer 配置。

隨便舉幾例:

public CorsConfigurer<HttpSecurity> cors() throws Exception {
 return getOrApply(new CorsConfigurer<>());
}
public CsrfConfigurer<HttpSecurity> csrf() throws Exception {
 ApplicationContext context = getContext();
 return getOrApply(new CsrfConfigurer<>(context));
}
public ExceptionHandlingConfigurer<HttpSecurity> exceptionHandling() throws Exception {
 return getOrApply(new ExceptionHandlingConfigurer<>());
}
 

HttpSecurity 中有大量類似的方法,過濾器鏈中的過濾器就是這樣一個一個配置的。我就不一一介紹了。

每個配置方法的結尾都會來一句 getOrApply,這個是干嘛的?

private <C extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>> C getOrApply(
  C configurer) throws Exception {
 C existingConfig = (C) getConfigurer(configurer.getClass());
 if (existingConfig != null) {
  return existingConfig;
 }
 return apply(configurer);
}
 

getConfigurer 方法是在它的父類 AbstractConfiguredSecurityBuilder 中定義的,目的就是去查看當前這個 xxxConfigurer 是否已經配置過了。

如果當前 xxxConfigurer 已經配置過了,則直接返回,否則調用 apply 方法,這個 apply 方法最終會調用到 AbstractConfiguredSecurityBuilder#add 方法,將當前配置 configurer 收集起來。

HttpSecurity 中還有一個 addFilter 方法:

public HttpSecurity addFilter(Filter filter) {
 Class<? extends Filter> filterClass = filter.getClass();
 if (!comparator.isRegistered(filterClass)) {
  throw new IllegalArgumentException(
    "The Filter class "
      + filterClass.getName()
      + " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.");
 }
 this.filters.add(filter);
 return this;
}
 

這個 addFilter 方法的作用,主要是在各個 xxxConfigurer 進行配置的時候,會調用到這個方法,(xxxConfigurer 就是用來配置過濾器的),把 Filter 都添加到 fitlers 變量中。

最終在 HttpSecurity 的 performBuild 方法中,構建出來一個過濾器鏈:

@Override
protected DefaultSecurityFilterChain performBuild() {
 filters.sort(comparator);
 return new DefaultSecurityFilterChain(requestMatcher, filters);
}

先給過濾器排序,然后構造 DefaultSecurityFilterChain 對象。

到此,關于“HttpSecurity是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

鹤岗市| 湄潭县| 潼关县| 隆化县| 内黄县| 双牌县| 定安县| 顺义区| 旺苍县| 卫辉市| 长岭县| 门头沟区| 府谷县| 河南省| 延吉市| 宣武区| 新津县| 乐亭县| 云安县| 仲巴县| 延边| 仙居县| 徐闻县| 赫章县| 石屏县| 长子县| 托克逊县| 大宁县| 中超| 宕昌县| 永平县| 淅川县| 清水河县| 呼伦贝尔市| 上蔡县| 武宁县| 乌兰察布市| 阿城市| 银川市| 无锡市| 清水县|