<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringSecurity過濾器原理

          共 4810字,需瀏覽 10分鐘

           ·

          2021-12-10 12:20

          點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”

          優(yōu)質(zhì)文章,第一時(shí)間送達(dá)



          -? ? ?主要過濾器鏈? ? -

          SpringSecurity的功能主要是由一系列的過濾器鏈相互配合完成的。驗(yàn)證一個(gè)過濾器之后放行到下一個(gè)過濾器鏈,然后到最后。



          -? ? ?認(rèn)證流程? ? -



          -? ? ?過濾器作用? ? -

          1. SecurityContextPersistenceFilter:會在每次請求處理之前從配置好的SecurityContextRepository中獲取SecurityContext安全上下文信息,然后加載到SecurityContextHolder中,然后在該次請求處理完成之后,將SecurityContextHolder中關(guān)于這次請求的信息存儲到一個(gè)“倉庫”中,然后將SecurityContextHolder中的信息清除,例如在Session中維護(hù)一個(gè)用戶的安全信息就是這個(gè)過濾器處理的。

          2. DefaultLoginPageGeneratingFilter:如果沒有配置自定義登錄頁面,那系統(tǒng)初始化時(shí)就會配置這個(gè)過濾器,并且用于在需要進(jìn)行登錄時(shí)生成一個(gè)登錄表單頁面。

          3. BasicAuthenticationFilter:檢測和處理http basic認(rèn)證。

          4. UsernamePasswordAuthenticationFilter:用于處理基于表單的登錄請求,從表單中獲取用戶名和密碼。默認(rèn)情況下處理來自/login的表單action。從表單中獲取用戶名和密碼時(shí),默認(rèn)使用的表單name屬性值為username和password,這倆個(gè)值也可以通過usernameParameter和passwordParameter在配置中自定義。

            這個(gè)過濾器在表單提交登錄請求之時(shí)會起作用。那么假設(shè)現(xiàn)在采用SpringSecurity整合Jwt,那么我需要配置一個(gè)Jwt登錄認(rèn)證類(繼承BasicAuthenticationFilter或者繼承OncePerRequestFilter都可以,因?yàn)锽asicAuthenticationFilter繼承了OncePerRequestFilter),重寫過濾器方法。Jwt的token認(rèn)證登錄是需要在在采用用戶名密碼登錄認(rèn)證之前,所以在配置Jwt登錄認(rèn)證類的時(shí)候需要在UsernamePasswordAuthenticationFilter之前添加過濾器。


            //配置自定義過濾器?添加jwt登錄授權(quán)過濾器
            //在過濾器UsernamePasswordAuthenticationFilter之前
            http.addFilterBefore(jwtAuthenticationFilter,UsernamePasswordAuthenticationFilter.class);
          5. RequestCacheAwareFilter:用來處理請求的緩存。

          6. SecurityContextHolderAwareRequestFilter:主要是包裝請求對象request。

          7. AnonymousAuthenticationFilter:檢測SecurityContextHolder中是否存在Authentication對象,如果不存在則為其提供一個(gè)匿名Authentication。

          8. SessionManagementFilter:管理Session的過濾器

          9. ExceptionTranslationFilter:捕獲來自過濾器鏈的所有異常,并進(jìn)行處理。但是只處理兩類異常:AccessDeniedException和AuthenticationException 異常,其他的異常會繼續(xù)拋出。

            如果捕獲到的AuthenticationException,那么將會使用其對應(yīng)的AuthenticationEntryPoint的commence()方法處理。在處理之前,ExceptionTranslationFilter先使用RequestCache將當(dāng)前的HTTPServletRequest的信息保存起來,方便用戶登錄成功后可以跳轉(zhuǎn)到之前的頁面。

            可以自定義AuthenticationException的處理方法。需要實(shí)現(xiàn)AuthenticationEntryPoint接口,然后重寫commence()方法。



            /**
            ?*?當(dāng)未登錄或者token失效時(shí)訪問接口自定義的返回結(jié)果
            ?*/
            @Component
            public?class?RestfulAuthorizationEntryPoint?implements?AuthenticationEntryPoint?{
            ????@Override
            ????public?void?commence(HttpServletRequest?request,?HttpServletResponse?response,?AuthenticationException?e)?throws?IOException,?ServletException?{
            ????????response.setCharacterEncoding("utf-8");
            ????????response.setContentType("application/json");
            ????????PrintWriter?writer?=?response.getWriter();
            ????????RespBean?bean?=?RespBean.error("請先登錄!");
            ????????bean.setCode(401);
            ????????writer.write(new?ObjectMapper().writeValueAsString(bean));
            ????????writer.flush();
            ????????writer.close();
            ????}
            }


            如果捕獲的AuthenticationDeniedException,那么將會根據(jù)當(dāng)前訪問的用戶是否已經(jīng)登錄認(rèn)證做不同的處理,如果未登錄,則會使用關(guān)聯(lián)的AuthenticationEntryPoint的commence()方法進(jìn)行處理,否則將使用關(guān)聯(lián)的AccessDeniedHandler的handle()方法進(jìn)行處理。

            可以進(jìn)行自定義AuthenticationDeniedException的處理方法。需要實(shí)現(xiàn)AccessDeniedHandler接口,然后重寫handle()方法。


            @Component
            public?class?RestfulAccessDeniedHandler?implements?AccessDeniedHandler?{
            ????@Override
            ????public?void?handle(HttpServletRequest?request,?HttpServletResponse?response,?AccessDeniedException?e)?throws?IOException,?ServletException?{
            ????????response.setCharacterEncoding("utf-8");
            ????????response.setContentType("application/json");
            ????????PrintWriter?writer?=?response.getWriter();
            ????????RespBean?error?=?RespBean.error("權(quán)限不足,聯(lián)系管理員!");
            ????????writer.write(new?ObjectMapper().writeValueAsString(error));
            ????????error.setCode(403);
            ????????writer.flush();
            ????????writer.close();
            ????}
            }
          10. FilterSecurityInterceptor:可以看做過濾器鏈的出口

          11. RememberMeAuthenticationFilter:當(dāng)用戶沒有登錄而直接訪問資源時(shí), 從 cookie 里找出用戶的信息, 如果 Spring Security 能夠識別出用戶提供的remember me cookie, 用戶將不必填寫用戶名和密碼, 而是直接登錄進(jìn)入系統(tǒng),該過濾器默認(rèn)不開啟。



          -? ? ?SecurityContextHolder? ? -

          SecurityContext對象是安全上下文信息,包括當(dāng)前使用系統(tǒng)的用戶的信息。每個(gè)用戶都會有它的安全上下文對象,所以把每一個(gè)用戶的SecurityContext保存到SecurityContextHolder中。

          SecurityContextHolder存儲SecurityContext的方式根據(jù)應(yīng)用場景不同也有區(qū)別:

          (1)單機(jī)系統(tǒng),即應(yīng)用從開啟到關(guān)閉的整個(gè)生命周期只有一個(gè)用戶在使用。由于整個(gè)應(yīng)用只需要保存一個(gè)SecurityContext(安全上下文即可)

          (2)多用戶系統(tǒng),比如典型的Web系統(tǒng),整個(gè)生命周期可能同時(shí)有多個(gè)用戶在使用。這時(shí)候應(yīng)用需要保存多個(gè)SecurityContext(安全上下文),需要利用ThreadLocal進(jìn)行保存,每個(gè)線程都可以利用ThreadLocal獲取其自己的SecurityContext,及安全上下文。ThreadLocal內(nèi)部會用數(shù)組來存儲多個(gè)對象的。原理是,ThreadLocal會為每個(gè)線程開辟一個(gè)存儲區(qū)域,來存儲相應(yīng)的對象。

          Authentication:用戶信息的表示

          在SecurityContextHolder中存儲了當(dāng)前與系統(tǒng)交互的用戶的信息。Spring Security使用一個(gè)Authentication 對象來表示這些信息。

          Authentication 主要包含了:

          • 用戶權(quán)限集合

          • 用戶證書(密碼)

          • 細(xì)節(jié)(Details)

          • Principal(就是這個(gè)用戶的賬戶信息)

          在自定義登錄認(rèn)證過濾器的時(shí)候,記得需要把用戶的信息(Authentication )保存到SecurityContextHolder中,以便后續(xù)用戶的正常使用。比如我在做和Jwt認(rèn)證的整合的時(shí)候,繼承OncePerRequestFilter,重寫doFilterInternal方法,認(rèn)證完token之后,就需要把用戶的信息存入安全上下文Holder中。

          UsernamePasswordAuthenticationToken?authenticationToken
          ????=new?UsernamePasswordAuthenticationToken(user,null,?null);
          authenticationToken.setDetails(new?WebAuthenticationDetailsSource()
          ???????????????????????????????.buildDetails(request));

          SecurityContextHolder.getContext().setAuthentication(authenticationToken);


          ? 作者?|??ins1mnia

          來源 |??cnblogs.com/ins1mnia/p/15635130.html


          加鋒哥微信:?java1239??
          圍觀鋒哥朋友圈,每天推送Java干貨!

          瀏覽 65
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  69激情网| 国产精品精品国产婷婷这里Av | 亚洲成人黄色在线观看 | 小h片免费 | 欧美黄A片免费视频www |