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

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

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

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

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

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

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

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

下面說(shuō)一下SpringSecurity自定義注解放行接口

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

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

感覺(jué)非常的不優(yōu)雅。所以想通過(guò)自定義一個(gè)注解,來(lái)進(jìn)行接口匿名訪問(wèn)。

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

@Target(ElementType.METHOD) //注解放置的目標(biāo)位置,METHOD是可注解在方法級(jí)別上
@Retention(RetentionPolicy.RUNTIME) //注解在哪個(gè)階段執(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()
                //不通過(guò)Session獲取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()

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

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

                // 除上面外的所有請(qǐng)求全部需要鑒權(quán)認(rèn)證
                .anyRequest().authenticated();
        //添加過(guò)濾器
        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 過(guò)濾器鏈,
     *                無(wú)法通過(guò) SecurityContextHolder 獲取到登錄用戶信息的,
     *                因?yàn)樗婚_(kāi)始沒(méi)經(jīng)過(guò) SecurityContextPersistenceFilter 過(guò)濾器鏈。
     * @ dateTime: 2021/7/19 10:22
     */
    

}

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

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

SpringSecurity提供了兩種放行方式

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

public void configure(WebSecurity web)

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

protected void configure(HttpSecurity http) 

使用走 Spring Security 過(guò)濾器鏈的放行方式

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

我們可以對(duì)此進(jìn)行遍歷,獲取攜帶了@IgnoreAuth的接口,再通過(guò)接口的請(qǐng)求方式進(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ù)請(qǐng)求類型做不同的處理
            info.getMethodsCondition().getMethods().forEach(requestMethod -> {
                switch (requestMethod) {
                    case GET:
                        // getPatternsCondition得到請(qǐng)求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;
                }
            });
        }
    }
});

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

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

使用不走 Spring Security 過(guò)濾器鏈的放行方式

代碼大體相同,都是首先獲取所有接口,再進(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ù)請(qǐng)求類型做不同的處理
                    info.getMethodsCondition().getMethods().forEach(requestMethod -> {
                        switch (requestMethod) {
                            case GET:
                                // getPatternsCondition得到請(qǐng)求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中引入這個(gè)模塊,這樣就可以在user-center中使用配置好的功能。

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

項(xiàng)目模塊為:

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

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

總結(jié)

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

相關(guān)文章

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

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

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

    Java @RequestMapping注解功能使用詳解

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

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

    這篇文章主要介紹了Java遍歷起止日期中間的所有日期操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    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)試的講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-03-03
  • 如何使用Java生成PDF文檔詳解

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

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

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

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

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

    本文主要介紹了Spring如何使用三級(jí)緩存解決循環(huán)依賴問(wèn)題,本文為了方便說(shuō)明,先設(shè)置兩個(gè)業(yè)務(wù)層對(duì)象,命名為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逐個(gè)字符讀寫及使用緩沖區(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),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04

最新評(píng)論

顺平县| 项城市| 安泽县| 扬州市| 秦皇岛市| 台北县| 东源县| 新郑市| 淅川县| 镶黄旗| 松溪县| 安远县| 洪湖市| 昭苏县| 东乌珠穆沁旗| 天镇县| 桐庐县| 池州市| 松桃| 凌源市| 建水县| 衢州市| 乌苏市| 孟州市| 涟水县| 景谷| 荥经县| 青冈县| 祥云县| 赤城县| 长兴县| 星座| 丰宁| 赞皇县| 公安县| 读书| 杨浦区| 临沭县| 平利县| 彭泽县| 余庆县|