成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

絕活!Spring Security過濾器就該這么配置

開發 架構
CaptchaAuthenticationFilter這個驗證碼過濾器是通過模仿UsernamePasswordAuthenticationFilter實現的。

以前胖哥帶大家用Spring Security過濾器實現了手機驗證碼認證,今天我們來改良一下驗證碼認證的配置方式。這絕對是絕活666,不再看、點贊一波嗎?天天白嫖,晚上睡得著覺?

CaptchaAuthenticationFilter這個驗證碼過濾器是通過模仿UsernamePasswordAuthenticationFilter實現的。同樣的道理,由于UsernamePasswordAuthenticationFilter的配置是由FormLoginConfigurer來完成的,應該也能模仿一下FormLoginConfigurer,寫一個配置類CaptchaAuthenticationFilterConfigurer去配置CaptchaAuthenticationFilter。

public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
AbstractAuthenticationFilterConfigurer<H, FormLoginConfigurer<H>, UsernamePasswordAuthenticationFilter> {

// 省略
}

AbstractAuthenticationFilterConfigurer

FormLoginConfigurer看起來有點復雜,不過繼承關系并不復雜,只繼承了AbstractAuthenticationFilterConfigurer。

public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecurityBuilder<B>, T extends AbstractAuthenticationFilterConfigurer<B, T, F>, F extends AbstractAuthenticationProcessingFilter>
extends AbstractHttpConfigurer<T, B> {
}

理論上我們模仿一下,也繼承一下這個類,但是你會發現這種方式行不通。因為AbstractAuthenticationFilterConfigurer只能Spring Security內部使用,不建議自定義。原因在于它最終向HttpSecurity添加過濾器使用的是HttpSecurity.addFilter(Filter)方法,這個方法只有內置過濾器(參見FilterOrderRegistration)才能使用。了解了這個機制之后,我們只能往上再抽象一層,去改造其父類AbstractHttpConfigurer。

改造過程

AbstractAuthenticationFilterConfigurer中的B是實際指的HttpSecurity,因此這個要保留;

T指的是它本身的實現,我們配置CaptchaAuthenticationFilter不需要下沉一層到FormLoginConfigurer這個繼承級別,直接在AbstractAuthenticationFilterConfigurer這個繼承級別實現即可,因此T這里指的就是需要配置類本身,也不需要再抽象化,因此是不需要的;同樣的原因F也不需要,很明確是CaptchaAuthenticationFilter,不需要再泛化。這樣CaptchaAuthenticationFilter的配置類結構可以這樣定義:

public class CaptchaAuthenticationFilterConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractHttpConfigurer<CaptchaAuthenticationFilterConfigurer<H>, H> {
// 不再泛化 具體化
private final CaptchaAuthenticationFilter authFilter;
// 特定的驗證碼用戶服務
private CaptchaUserDetailsService captchaUserDetailsService;
// 驗證碼處理服務
private CaptchaService captchaService;
// 保存認證請求細節的策略
private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource;
// 默認使用保存請求認證成功處理器
private SavedRequestAwareAuthenticationSuccessHandler defaultSuccessHandler = new SavedRequestAwareAuthenticationSuccessHandler();
// 認證成功處理器
private AuthenticationSuccessHandler successHandler = this.defaultSuccessHandler;
// 登錄認證端點
private LoginUrlAuthenticationEntryPoint authenticationEntryPoint;
// 是否 自定義頁面
private boolean customLoginPage;
// 登錄頁面
private String loginPage;
// 登錄成功url
private String loginProcessingUrl;
// 認證失敗處理器
private AuthenticationFailureHandler failureHandler;
// 認證路徑是否放開
private boolean permitAll;
// 認證失敗的url
private String failureUrl;

/**
* Creates a new instance with minimal defaults
*/
public CaptchaAuthenticationFilterConfigurer() {
setLoginPage("/login/captcha");
this.authFilter = new CaptchaAuthenticationFilter();
}

public CaptchaAuthenticationFilterConfigurer<H> formLoginDisabled() {
this.formLoginEnabled = false;
return this;
}

public CaptchaAuthenticationFilterConfigurer<H> captchaUserDetailsService(CaptchaUserDetailsService captchaUserDetailsService) {
this.captchaUserDetailsService = captchaUserDetailsService;
return this;
}

public CaptchaAuthenticationFilterConfigurer<H> captchaService(CaptchaService captchaService) {
this.captchaService = captchaService;
return this;
}

public CaptchaAuthenticationFilterConfigurer<H> usernameParameter(String usernameParameter) {
authFilter.setUsernameParameter(usernameParameter);
return this;
}

public CaptchaAuthenticationFilterConfigurer<H> captchaParameter(String captchaParameter) {
authFilter.setCaptchaParameter(captchaParameter);
return this;
}

public CaptchaAuthenticationFilterConfigurer<H> parametersConverter(Converter<HttpServletRequest, CaptchaAuthenticationToken> converter) {
authFilter.setConverter(converter);
return this;
}
@Override
public void init(H http) throws Exception {
updateAuthenticationDefaults();
updateAccessDefaults(http);
registerDefaultAuthenticationEntryPoint(http);
// 這里禁用默認頁面過濾器 如果你想自定義登錄頁面 可以自行實現 可能和FormLogin沖突
// initDefaultLoginFilter(http);
// 把對應的Provider也在init時寫入HttpSecurity
initProvider(http);
}
@Override
public void configure(H http) throws Exception {

//這里改為使用前插過濾器方法
http.addFilterBefore(filter, LogoutFilter.class);
}

// 其它方法 同AbstractAuthenticationFilterConfigurer
}

其實就是模仿AbstractAuthenticationFilterConfigurer及其實現類的風格把用的配置項實現一遍。這里值得一提的是CaptchaService的配置也可以從Spring IoC中查找(參考getBeanOrNull方法,這個方法在Spring Security中隨處可見,建議借鑒),這樣更加靈活,既能從方法配置也能自動注入。

   private void initProvider(H http) {

ApplicationContext applicationContext = http.getSharedObject(ApplicationContext.class);
// 沒有配置CaptchaUserDetailsService就去Spring IoC獲取
if (captchaUserDetailsService == null) {
captchaUserDetailsService = getBeanOrNull(applicationContext, CaptchaUserDetailsService.class);
}
// 沒有配置CaptchaService就去Spring IoC獲取
if (captchaService == null) {
captchaService = getBeanOrNull(applicationContext, CaptchaService.class);
}
// 初始化 Provider
CaptchaAuthenticationProvider captchaAuthenticationProvider = this.postProcess(new CaptchaAuthenticationProvider(captchaUserDetailsService, captchaService));
// 會增加到ProviderManager的注冊列表中
http.authenticationProvider(captchaAuthenticationProvider);
}

配置類效果

我們來看看CaptchaAuthenticationFilterConfigurer的配置效果:

  @Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http, UserDetailsService userDetailsService) throws Exception {


http.csrf().disable()
.authorizeRequests()
.mvcMatchers("/foo/**").access("hasAuthority('ROLE_USER')")
.anyRequest().authenticated()
.and()
// 所有的 AbstractHttpConfigurer 都可以通過apply方法加入HttpSecurity
.apply(new CaptchaAuthenticationFilterConfigurer<>())
// 配置驗證碼處理服務 這里直接true 方便測試
.captchaService((phone, rawCode) -> true)
// 通過手機號去拿驗證碼,這里為了方便直接寫死了,實際phone和username做個映射
.captchaUserDetailsService(phone -> userDetailsService.loadUserByUsername("felord"))
// 默認認證成功跳轉到/路徑 這里改造成把認證信息直接返回json
.successHandler((request, response, authentication) -> {
// 這里把認證信息以JSON形式返回
ServletServerHttpResponse servletServerHttpResponse = new ServletServerHttpResponse(response);
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
mappingJackson2HttpMessageConverter.write(authentication, MediaType.APPLICATION_JSON,servletServerHttpResponse);
});

return http.build();
}

是不是要優雅很多,解決了你自己配置過濾器的很多疑難雜癥。學習一定要模仿,先模仿成功,然后再分析思考為什么會模仿成功,最后形成自己的創造力。千萬不要被一些陌生概念唬住,有些改造是不需要去深入了解細節的。

本文轉載自微信公眾號「碼農小胖哥」,可以通過以下二維碼關注。轉載本文請聯系碼農小胖哥公眾號。

責任編輯:武曉燕 來源: 碼農小胖哥
相關推薦

2022-02-21 23:58:49

Spring過濾器順序值

2009-07-08 16:07:04

Servlet過濾器配

2022-02-10 14:54:31

Spring容器過濾器

2022-02-14 07:32:13

Spring過濾器鏈Matcher

2023-01-26 01:41:27

核心全局過濾器

2021-07-05 15:22:03

Servlet過濾器客戶端

2017-04-12 14:43:01

Spring ClouZuul過濾器

2024-01-05 09:04:35

隆過濾器數據結構哈希函數

2024-11-04 08:45:48

布隆過濾器元數據指紋值

2021-01-14 08:13:39

Spring Clou應用內置過濾器

2017-05-04 22:30:17

Zuul過濾器微服務

2009-07-08 15:30:56

Servlet過濾器

2009-07-14 09:09:08

Swing模型過濾器

2009-09-29 13:55:23

Hibernate設置

2011-06-29 16:14:59

Qt 事件 過濾器

2025-02-25 00:11:40

Servlet服務器Web

2025-02-03 08:16:56

2025-04-21 00:50:50

2009-06-18 10:13:00

Hibernate過濾

2017-07-18 14:10:31

大數據Apache Flum過濾器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩福利在线观看 | 色综合久久久久 | 伊人艹 | 秋霞a级毛片在线看 | 黄色毛片在线观看 | www.99热这里只有精品 | 国产精品久久久久久久久久东京 | 欧美精品福利视频 | 欧美日韩成人一区二区 | 99免费视频 | 日韩欧美一区二区三区在线播放 | 成人在线中文字幕 | 中文一区二区视频 | 天堂网中文字幕在线观看 | 精久久 | 国产一区二区三区免费观看在线 | 久久久久一区二区 | 精品国产乱码久久久久久丨区2区 | 国产一区二区三区 | 国产三级国产精品 | 欧美日韩国产一区二区三区 | 欧美一区二区在线播放 | 99精品久久99久久久久 | 国产成人免费视频网站高清观看视频 | 亚洲精品黄 | 精品国产乱码久久久久久中文 | 国产成人精品一区二区三区视频 | 久久久精 | 免费影视在线观看 | 操久久久 | 99久久国产 | 久久黄网| 精品福利在线 | 国产毛片视频 | 成人av免费看| 爱爱视频网| 亚洲精品日韩精品 | 国产欧美精品一区二区 | 久久国产精品首页 | av一级久久| 伊人影院99|