欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Security6.4.2?自定義異常中統(tǒng)一響應(yīng)遇到的問(wèn)題

 更新時(shí)間:2025年03月14日 11:36:43   作者:陽(yáng)光曉楓ya  
本文主要介紹了Security6.4.2?自定義異常中統(tǒng)一響應(yīng)遇到的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

背景

進(jìn)行前后端分離開(kāi)發(fā),在登錄認(rèn)證過(guò)程中需要拋出token異常,但是異常被servlet捕獲并打印在控制臺(tái),而前端返回 "Full authentication is required to access this resource"(訪問(wèn)此資源需要完全認(rèn)證)。

解決辦法

在自定義的過(guò)濾器里打斷點(diǎn),查看該異常所在的過(guò)濾器是否在ExceptionTranslationFilter這個(gè)過(guò)濾器的后面,如果不在,則使用

.addFilterAfter(異常所在的過(guò)濾器, ExceptionTranslationFilter.class)

問(wèn)題解決~

一、理想情況

在登錄認(rèn)證處理過(guò)程中一般都會(huì)涉及到Token的處理,比如Token過(guò)期、錯(cuò)誤等。在正常的處理流程中我們應(yīng)該是在新建一個(gè)JwtFillter類來(lái)重寫(xiě)OncePerRequestFilter的doFilterInternal方法。比如:

@Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        
        // 令牌驗(yàn)證
        final String token = request.getHeader("Authorization");
        final String jwt;
        if (StringUtils.isEmpty(token)){
            throw new BadCredentialsException("Token無(wú)效");
        }
    }

由于security默認(rèn)屏蔽UsernameNotFoundException并將其轉(zhuǎn)換成BadCredentialsException處理,為了安全考慮,建議使用BadCredentialsException來(lái)拋給security處理。

然后在SecurityConfig類中配置過(guò)濾器鏈,如:

@Configuration
public class SecurityConfiguration {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public JwtFillter jwtFillter() {
        return new JwtFillter();
    }

    @Bean
    public AuthenticationEntryPoint myAuthenticationEntryPoint() {
        return new MyAuthenticationEntryPoint();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        // 自定義配置
        http.authorizeHttpRequests((requests -> requests
//                        .requestMatchers("/product/list").hasAuthority("PRODUCT_LIST")
//                        .requestMatchers("/product/save").hasAuthority("PRODUCT_SAVE")
//                        .requestMatchers("/product/list").hasRole("USER")
//                        .requestMatchers("/product/save").hasRole("ADMIN")
                        .requestMatchers("/user/info").hasRole("ADMIN")
                        .anyRequest().authenticated())
                )
                .addFilterBefore(jwtFillter(), AuthenticationFilter.class)
                .exceptionHandling(exception ->{
                    exception.authenticationEntryPoint(myAuthenticationEntryPoint());
                })
                .csrf(AbstractHttpConfigurer::disable)
                .formLogin(AbstractHttpConfigurer::disable);
        // 返回新的過(guò)濾器鏈
        return http.build();
    }
}

由于我禁用了formLogin登錄表單,與之相關(guān)的UsernamePasswordAuthenticationFilter等過(guò)濾器會(huì)從過(guò)濾器鏈中移除,所以一般都會(huì)設(shè)置為在 AuthenticationFilter之前( AuthenticationFilter是最后一道過(guò)濾器)

為了實(shí)現(xiàn)前后端分離,要根據(jù)發(fā)生的異常告訴前端如何處理,所以還需要自定義一個(gè)AuthenticationEntryPoint認(rèn)證異常處理器(授權(quán)異常處理器的邏輯相同)并將其加入過(guò)濾器鏈中,我的自定義認(rèn)證異常處理類如下:

public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        // 向前端響應(yīng)數(shù)據(jù)
        ResponseUtil.print(response,Result.error(authException.getMessage()));
    }
}

(此處ResponseUtil和Result為我自定義的工具類,與本次事件無(wú)關(guān))

然后在這里進(jìn)行異常處理邏輯,通過(guò)authException獲取異常信息,然后就能正常將json格式的響應(yīng)信息發(fā)送給前端。

二、發(fā)生異常

但是當(dāng)運(yùn)行代碼后,得到的響應(yīng)結(jié)果卻與預(yù)期不符

而后端控制臺(tái)也打印了一堆錯(cuò)誤棧信息

很明顯,該BadCredentialsException異常本應(yīng)該被security捕獲,結(jié)果居然被servlet容器給捕獲了。仔細(xì)檢查代碼后能確定除了SecurityConfig以外都沒(méi)有問(wèn)題,那大概率是過(guò)濾器順序有問(wèn)題。找了很多資料都沒(méi)有相應(yīng)的解決辦法(可能是我找的還不夠多[doge])。

三、異常原因

既然是過(guò)濾器順序有問(wèn)題,那就看一下過(guò)濾器鏈吧(可惡,想了好久才想起來(lái)這一點(diǎn))

在JwtFillter(你自己的jwt過(guò)濾器)里設(shè)置斷點(diǎn),查看filterChain里的過(guò)濾器順序,發(fā)現(xiàn)JwtFillter在中間的位置,而ExceptionTranslationFilter和AuthorizationFilter在最后面,我還以為

.addFilterBefore(jwtFillter(), AuthenticationFilter.class)

這段代碼是將我的過(guò)濾器放在AuthorizationFilter的前一個(gè)位置呢,結(jié)果跑那么前面去了。然后再來(lái)看一下ExceptionTranslationFilter是如何處理認(rèn)證異常的:

private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            chain.doFilter(request, response);// 此處對(duì)后續(xù)的鏈路進(jìn)行異常捕獲
        } catch (IOException var7) {
            throw var7;
        } catch (Exception var8) {
            Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(var8);
            RuntimeException securityException = (AuthenticationException)this.throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class, causeChain);
            if (securityException == null) {
                securityException = (AccessDeniedException)this.throwableAnalyzer.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
            }

            if (securityException == null) {
                this.rethrow(var8);
            }

            if (response.isCommitted()) {
                throw new ServletException("Unable to handle the Spring Security Exception because the response is already committed.", var8);
            }

            this.handleSpringSecurityException(request, response, chain, (RuntimeException)securityException);
        }

    }

 可以看到,該過(guò)濾器是對(duì)后續(xù)的鏈路進(jìn)行異常捕獲,所以自定義的JwtFilter應(yīng)當(dāng)放在ExceptionTranslationFilter的后面,即

.addFilterAfter(jwtFillter(), ExceptionTranslationFilter.class)

于是,該異常便能正確被security捕獲并發(fā)送給自定義認(rèn)證異常處理器進(jìn)行處理。所以寫(xiě)過(guò)濾器的時(shí)候一定要注意檢查鏈路順序啊[吐血]

不過(guò)我跟著視頻學(xué)習(xí)的時(shí)候,對(duì)方并沒(méi)有設(shè)置這個(gè)也能在自定義異常處理器中獲取異常信息,就很奇怪.....估計(jì)是Security的版本不同導(dǎo)致的吧

到此這篇關(guān)于Security6.4.2 自定義異常中統(tǒng)一響應(yīng)遇到的問(wèn)題的文章就介紹到這了,更多相關(guān)Security6.4.2 自定義異常統(tǒng)一響應(yīng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java 如何判斷是否是26個(gè)英文字母

    java 如何判斷是否是26個(gè)英文字母

    這篇文章主要介紹了java 如何判斷是否是26個(gè)英文字母的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-01-01
  • 理解Java訪問(wèn)權(quán)限控制

    理解Java訪問(wèn)權(quán)限控制

    這篇文章主要幫助大家深入的理解Java訪問(wèn)權(quán)限控制,為何需要訪問(wèn)控制權(quán)限,本文給出了解釋,感興趣的小伙伴們可以參考一下
    2016-02-02
  • 基于visualvm監(jiān)控類實(shí)現(xiàn)過(guò)程詳解

    基于visualvm監(jiān)控類實(shí)現(xiàn)過(guò)程詳解

    這篇文章主要介紹了基于visualvm監(jiān)控類實(shí)現(xiàn)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • 詳解SpringCloud-OpenFeign組件的使用

    詳解SpringCloud-OpenFeign組件的使用

    這篇文章主要介紹了SpringCloud-OpenFeign組件的使用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Springboot?2.x?RabbitTemplate默認(rèn)消息持久化的原因解析

    Springboot?2.x?RabbitTemplate默認(rèn)消息持久化的原因解析

    這篇文章主要介紹了Springboot?2.x?RabbitTemplate默認(rèn)消息持久化的原因解析,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • Springboot Logback日志多文件輸出方式(按日期和大小分割)

    Springboot Logback日志多文件輸出方式(按日期和大小分割)

    這篇文章主要介紹了Springboot Logback日志多文件輸出方式(按日期和大小分割),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Mybatis執(zhí)行流程、緩存原理及相關(guān)面試題匯總

    Mybatis執(zhí)行流程、緩存原理及相關(guān)面試題匯總

    最近剛學(xué)完MyBatis,趁著大好機(jī)會(huì),總結(jié)一下它的執(zhí)行流程,面試也愛(ài)問(wèn)這個(gè),下面這篇文章主要給大家介紹了關(guān)于Mybatis執(zhí)行流程、緩存原理及相關(guān)面試題的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • 詳解Java中的do...while循環(huán)語(yǔ)句的使用方法

    詳解Java中的do...while循環(huán)語(yǔ)句的使用方法

    這篇文章主要介紹了Java中的do...while循環(huán)語(yǔ)句的使用方法,是Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-10-10
  • 詳解SpringBoot 解決攔截器注入Service為空問(wèn)題

    詳解SpringBoot 解決攔截器注入Service為空問(wèn)題

    這篇文章主要介紹了詳解SpringBoot 解決攔截器注入Service為空問(wèn)題的解決,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-06-06
  • resttemplate設(shè)置params的方法

    resttemplate設(shè)置params的方法

    RestTemplate設(shè)置請(qǐng)求參數(shù)的方式根據(jù)請(qǐng)求類型(GET/POST)和參數(shù)形式(路徑參數(shù)、查詢參數(shù)、JSON請(qǐng)求體)有所不同,下面通過(guò)本文給大家介紹resttemplate設(shè)置params的方法,感興趣的朋友一起看看吧
    2025-04-04

最新評(píng)論