最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringSecurity自定義注解放行以及在微服務(wù)架構(gòu)中使用詳解

 更新時間:2026年03月13日 16:29:28   作者:胡思亂想罷了~  
文章介紹了SpringSecurity的認(rèn)證流程,包括過濾器鏈的使用、AuthenticationFilter的作用、認(rèn)證管理器的認(rèn)證過程,以及如何通過自定義注解實(shí)現(xiàn)接口匿名訪問

SpringSecurity的認(rèn)證流程:(個人理解)

Spring Security通過一系列的過濾器組成的過濾鏈來處理安全相關(guān)的任務(wù)。在Web應(yīng)用中,過濾器鏈主要用于實(shí)現(xiàn)身份驗(yàn)證、授權(quán)、記住我(Remember Me)等安全功能。

請求先到AuthenticationFilter,首先先驗(yàn)證使用的什么協(xié)議(只允許post請求),再獲取賬號密碼,將賬號密碼封裝成authentication,通常是封裝成UsernamePasswordAuthenticationToken。注意此處有多種過濾器,BasicAuthenticationFilter,UsernamePasswordAuthenticationFilter,RememberMeAuthenticationFilter,SocialAuthenticationFilter,Oauth2AuthenticationProcessingFilter和Oauth2ClientAuthenticationProcessingFilter只有其中一個認(rèn)證通過就會封裝authentication對象并返回。

然后調(diào)用authenticationManager中的authentication方法進(jìn)行認(rèn)證,認(rèn)證成功返回authentication,認(rèn)證失敗AuthenticationManager會根據(jù)不同的認(rèn)證方式選擇對應(yīng)的Provider進(jìn)行認(rèn)證。

providerManage實(shí)現(xiàn)了AuthenticationManage的多種方法,通過調(diào)用其中的DaoAuthenticationprovider方法根據(jù)用戶名加載用戶信息,通過userDetail進(jìn)行接收后封裝為authentication對象并依次返回,返回到AuthenticationFilter時,通過AuthenticationManage進(jìn)行認(rèn)證,最后將主題信息返回到security的上下文中(就是保存Authentication對象),下次請求來的時候在securityContextPersistenceFilter中將Authentication拿出來,后續(xù)認(rèn)證就不需要了。

下面說一下SpringSecurity自定義注解放行接口

應(yīng)用場景:實(shí)際項(xiàng)目開發(fā)中,會遇到需要放行一些接口,使其能匿名訪問的業(yè)務(wù)需求。但是每當(dāng)需要當(dāng)需要放行時,都需要在security的配置類中進(jìn)行修改,例如

//                .antMatchers("captcha/check").anonymous()

感覺非常的不優(yōu)雅。所以想通過自定義一個注解,來進(jìn)行接口匿名訪問。

首先創(chuàng)建一個自定義注解:

@Target(ElementType.METHOD) //注解放置的目標(biāo)位置,METHOD是可注解在方法級別上
@Retention(RetentionPolicy.RUNTIME) //注解在哪個階段執(zhí)行
@Documented //生成文檔
public @interface IgnoreAuth {
}

然后編寫securityConfig類繼承WebSecurityConfigurerAdapter:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

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

    @Autowired
    private JwtAuthenticationTokenFilter filter;

    @Resource
    private AuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    private RequestMappingHandlerMapping requestMappingHandlerMapping;


    @Resource
    private AccessDeniedHandler accessDeniedHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {



        http
                //關(guān)閉csrf
                .csrf().disable()
                //不通過Session獲取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()

                // 對于登錄接口 允許匿名訪問 未登錄狀態(tài)也可以訪問

                .antMatchers("/token/refreshToken").anonymous()
//                 需要用戶帶有管理員權(quán)限
                .antMatchers("/find").hasRole("管理員")
                // 需要用戶具備這個接口的權(quán)限
                .antMatchers("/find").hasAuthority("menu:user")

                // 除上面外的所有請求全部需要鑒權(quán)認(rèn)證
                .anyRequest().authenticated();
        //添加過濾器
        http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);

        //配置異常處理器
        http.exceptionHandling()
                //配置認(rèn)證失敗處理器
                .authenticationEntryPoint(authenticationEntryPoint)
                .accessDeniedHandler(accessDeniedHandler);

        //允許跨域
        http.cors();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


    /**
     * @ description: 使用這種方式放行的接口,不走 Spring Security 過濾器鏈,
     *                無法通過 SecurityContextHolder 獲取到登錄用戶信息的,
     *                因?yàn)樗婚_始沒經(jīng)過 SecurityContextPersistenceFilter 過濾器鏈。
     * @ dateTime: 2021/7/19 10:22
     */
    

}

自定義注解實(shí)現(xiàn)

說明:下面兩種放行方式不能在有@ResquestMapper注解的接口上面使用,只能在@GetMapper,@PostMapper的接口中使用,因?yàn)槲沂峭ㄟ^請求方式進(jìn)行放行的。

SpringSecurity提供了兩種放行方式

1.使用這種方式放行的接口,不走 Spring Security 過濾器鏈,

public void configure(WebSecurity web)

2.使用這種方式放行的接口,走 Spring Security 過濾器鏈,

protected void configure(HttpSecurity http) 

使用走 Spring Security 過濾器鏈的放行方式

RequestMappingHandlerMapping組件可以獲取系統(tǒng)中的所有接口,如圖

我們可以對此進(jìn)行遍歷,獲取攜帶了@IgnoreAuth的接口,再通過接口的請求方式進(jìn)行放行

Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
System.out.println("handlerMethods:" + handlerMethods);
handlerMethods.forEach((info, method) -> {
    if (info.getMethodsCondition().getMethods().size() != 0) {

        // 帶IgnoreAuth注解的方法直接放行
        if (!Objects.isNull(method.getMethodAnnotation(IgnoreAuth.class))) {
            // 根據(jù)請求類型做不同的處理
            info.getMethodsCondition().getMethods().forEach(requestMethod -> {
                switch (requestMethod) {
                    case GET:
                        // getPatternsCondition得到請求url數(shù)組,遍歷處理
                        info.getPathPatternsCondition().getPatterns().forEach(pattern -> {
                            // 放行
                            try {
                                http.authorizeRequests()
                                        .antMatchers(HttpMethod.GET, pattern.getPatternString())
                                        .anonymous();
                            } catch (Exception e) {
                                throw new RuntimeException(e);
                            }
                        });
                        break;
                    case POST:
                        info.getPathPatternsCondition().getPatterns().forEach(pattern -> {
                            try {
                                http.authorizeRequests()
                                        .antMatchers(HttpMethod.POST, pattern.getPatternString())
                                        .anonymous();
                            } catch (Exception e) {
                                throw new RuntimeException(e);
                            }
                        });
                        break;
                    case DELETE:
                        info.getPathPatternsCondition().getPatterns().forEach(pattern -> {
                            try {
                                http.authorizeRequests()
                                        .antMatchers(HttpMethod.DELETE, pattern.getPatternString())
                                        .anonymous();
                            } catch (Exception e) {
                                throw new RuntimeException(e);
                            }
                        });
                        break;
                    case PUT:
                        info.getPathPatternsCondition().getPatterns().forEach(pattern -> {
                            try {
                                http.authorizeRequests()
                                        .antMatchers(HttpMethod.PUT, pattern.getPatternString())
                                        .anonymous();
                            } catch (Exception e) {
                                throw new RuntimeException(e);
                            }
                        });
                        break;
                    default:
                        break;
                }
            });
        }
    }
});

需要注意的是,此處可能由于版本的不同,獲取請求名稱的方式有所不同。

這里通過pathPatternsCondition進(jìn)行獲取,某些版本需要在patternsCondition中進(jìn)行獲取,具體看個人的版本情況。

使用不走 Spring Security 過濾器鏈的放行方式

代碼大體相同,都是首先獲取所有接口,再進(jìn)行遍歷放行

        WebSecurity and = web.ignoring().and();
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
//        System.out.println("handlerMethods:" + handlerMethods);

        handlerMethods.forEach((info, method) -> {
            if (info.getMethodsCondition().getMethods().size() != 0) {

                // 帶IgnoreAuth注解的方法直接放行
                if (!Objects.isNull(method.getMethodAnnotation(IgnoreAuth.class))) {
                    // 根據(jù)請求類型做不同的處理
                    info.getMethodsCondition().getMethods().forEach(requestMethod -> {
                        switch (requestMethod) {
                            case GET:
                                // getPatternsCondition得到請求url數(shù)組,遍歷處理
                                info.getPathPatternsCondition().getPatterns().forEach(pattern -> {
                                    // 放行
                                    and.ignoring().antMatchers(HttpMethod.GET, pattern.getPatternString());

                                });
                                break;
                            case POST:
                                info.getPathPatternsCondition().getPatterns().forEach(pattern -> {
                                    and.ignoring().antMatchers(HttpMethod.POST,  pattern.getPatternString());
                                });
                                break;
                            case DELETE:
                                info.getPathPatternsCondition().getPatterns().forEach(pattern -> {
                                    and.ignoring().antMatchers(HttpMethod.DELETE,  pattern.getPatternString());
                                });
                                break;
                            case PUT:
                                info.getPathPatternsCondition().getPatterns().forEach(pattern -> {
                                    and.ignoring().antMatchers(HttpMethod.PUT,  pattern.getPatternString());
                                });
                                break;
                            default:
                                break;
                        }
                    });
                }
            }
        });

    }

在微服務(wù)架構(gòu)中進(jìn)行使用

在微服務(wù)中,我們需要在不同的模塊中實(shí)現(xiàn)單點(diǎn)登錄,或使用到SpingSecurity的認(rèn)證鑒權(quán),或使用自己定義的放行注解。下面是我的解決方式。

項(xiàng)目模塊為:

在springSecurity模塊中配置了Jwt登錄攔截,Redis,SpringSecurity配置等。

然后只需要在user-center中引入這個模塊,這樣就可以在user-center中使用配置好的功能。

在不同的模塊中實(shí)現(xiàn)單點(diǎn)登錄,或使用到SpingSecurity的認(rèn)證鑒權(quán),或使用自己定義的放行注解。下面是我的解決方式。

項(xiàng)目模塊為:

在springSecurity模塊中配置了Jwt登錄攔截,Redis,SpringSecurity配置等。

然后只需要在user-center中引入這個模塊,這樣就可以在user-center中使用配置好的功能。

總結(jié)

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java中雙冒號(::)運(yùn)算操作符用法詳解

    Java中雙冒號(::)運(yùn)算操作符用法詳解

    這篇文章主要給大家介紹了關(guān)于Java中雙冒號(::)運(yùn)算操作符用法的相關(guān)資料,雙冒號運(yùn)算操作符是類方法的句柄,lambda表達(dá)式的一種簡寫,這種簡寫的學(xué)名叫eta-conversion或者叫η-conversion,需要的朋友可以參考下
    2023-11-11
  • Java @RequestMapping注解功能使用詳解

    Java @RequestMapping注解功能使用詳解

    通過@RequestMapping注解可以定義不同的處理器映射規(guī)則,下面這篇文章主要給大家介紹了關(guān)于SpringMVC中@RequestMapping注解用法的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-11-11
  • Java遍歷起止日期中間的所有日期操作

    Java遍歷起止日期中間的所有日期操作

    這篇文章主要介紹了Java遍歷起止日期中間的所有日期操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • SpringBoot配置攔截器方式實(shí)例代碼

    SpringBoot配置攔截器方式實(shí)例代碼

    在本篇文章里小編給大家分享的是關(guān)于SpringBoot配置攔截器方式實(shí)例代碼,有需要的朋友們可以參考下。
    2020-04-04
  • Tomcat使用IDEA遠(yuǎn)程Debug調(diào)試的講解

    Tomcat使用IDEA遠(yuǎn)程Debug調(diào)試的講解

    今天小編就為大家分享一篇關(guān)于Tomcat使用IDEA遠(yuǎn)程Debug調(diào)試的講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • 如何使用Java生成PDF文檔詳解

    如何使用Java生成PDF文檔詳解

    這篇文章主要給大家介紹了關(guān)于如何使用Java生成PDF文檔的相關(guān)資料,PDF是可移植文檔格式,是一種電子文件格式,具有許多其他電子文檔格式無法相比的優(yōu)點(diǎn),需要的朋友可以參考下
    2023-07-07
  • Java  隊(duì)列實(shí)現(xiàn)原理及簡單實(shí)現(xiàn)代碼

    Java 隊(duì)列實(shí)現(xiàn)原理及簡單實(shí)現(xiàn)代碼

    這篇文章主要介紹了Java 隊(duì)列實(shí)現(xiàn)原理及簡單實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • Spring為什么要用三級緩存解決循環(huán)依賴呢

    Spring為什么要用三級緩存解決循環(huán)依賴呢

    本文主要介紹了Spring如何使用三級緩存解決循環(huán)依賴問題,本文為了方便說明,先設(shè)置兩個業(yè)務(wù)層對象,命名為AService和BService,結(jié)合示例給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2025-01-01
  • Java基于字符流形式讀寫數(shù)據(jù)的兩種實(shí)現(xiàn)方法示例

    Java基于字符流形式讀寫數(shù)據(jù)的兩種實(shí)現(xiàn)方法示例

    這篇文章主要介紹了Java基于字符流形式讀寫數(shù)據(jù)的兩種實(shí)現(xiàn)方法示,結(jié)合實(shí)例形式分析了java逐個字符讀寫及使用緩沖區(qū)進(jìn)行讀寫操作的具體實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2018-01-01
  • springboot+websocket+redis搭建的實(shí)現(xiàn)

    springboot+websocket+redis搭建的實(shí)現(xiàn)

    這篇文章主要介紹了springboot+websocket+redis搭建的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04

最新評論

镇远县| 油尖旺区| 昌邑市| 宜兴市| 山东省| 贞丰县| 民勤县| 图们市| 乌兰县| 饶阳县| 平顺县| 阿城市| 太原市| 苗栗县| 蛟河市| 洛隆县| 达州市| 田阳县| 开阳县| 德安县| 灵台县| 博爱县| 海门市| 镇江市| 新干县| 西乌珠穆沁旗| 陆川县| 于都县| 佛冈县| 米脂县| 社旗县| 台北市| 淳化县| 襄樊市| 乌海市| 吉安县| 江口县| 革吉县| 呼和浩特市| 如皋市| 吉安县|