spring security架構(一)


安全歸根節點需要解決兩個問題:

  • 鑒權(authentication)--我是誰?
  • 授權(authorization)--允許我做什么?

后者有些時候也被人們叫做“訪問控制”(access control)。spring security 是一個將鑒權和授權分開的安全框架。包含策略,同時提供對兩者的擴展能力。

Authencation Architecture

下圖描繪了spring security在鑒權處理流程中涉及到的類和過濾器。

  1.  外部的http請求訪問內部受保護的Resful API之前,需要經過一系列的安全過濾器。這些被spring security設定的過濾器,用於鑒權和授權的目的。當用戶的鑒權請求從外部進入時,將經過這條過濾器鏈,基於鑒權機制和模型,找到相應的Authentication Filter。比如說:
    • HTTP Basic authentication request 經過“過濾鏈”,直到它到達BasicAuthenticationFilter 過濾器進行處理。
    • HTTP Digest authentication request 經過“過濾鏈”,直到它到達DigestAuthenticationFilter 過濾器進行處理。
    • login form authentication request 經過“過濾鏈”,直到它到達UsernamePasswordAuthenticationFilter過濾器進行處理。
    • x509 authentication request 經過“過濾鏈”,直到它到達X509AuthenticationFilter 過濾器進行處理。
  2. 一旦鑒權請求被相應的Authentication Filter接收,該過濾器將會從接收的請求中提取出用戶名和密碼,基於這些用戶信息,創建一個  UsernamePasswordAuthenticationToken 對象,注意,該類實現了 Authentication 接口。
  3. UsernamePasswordAuthenticationToken  對象創建成功后,被用來作為 AuthenticationManager 中 authenticate() 方法的入參。 AuthenticationManager 僅僅是一個接口:
    public interface AuthenticationManager{
      Authentication authenticate(Authentication authentication)throws AuthenticationException;
    }
    

    實際實現類是 ProviderManager 。該實現類包含了一系列配置的 AuthenticationProvider (s), 這些provider受ProvideManager委托,用於用戶請求的鑒權。

  4. 具體到實現細節, ProviderManager 會遍歷每個AuthenticationProvider,根據傳入的Authentication對象(例如: UsernamePasswordAuthenticationToken )嘗試鑒權用戶。AuthenticationProvider 接口如下所示:

    public interface AuthenticationProvider { 
        Authentication authenticate(Authentication authentication) throws AuthenticationException; 
        boolean supports(Class<?> authentication);
    }
    

    這里是一些Spring security框架提供的AuthenticationProvider:

    • CasAuthenticationProvider
    • JaasAuthenticationProvider
    • DaoAuthenticationProvider
    • OpenIDAuthenticationProvider
    • RememberMeAuthenticationProvider
    • LdapAuthenticationProvider
  5. 有些AuthenticationProvider可能會使用 UserDetailsService ,用於獲取用戶的詳細信息。比如說 DaoAuthenticationProvider 可能需要根據傳入的用戶名從數據庫中獲取該用戶的詳細信息。
    public interface UserDetailsService{
      UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
    }
    

     

  6.  UserDetailsService 返回 UserDetails 。而 User 是 UserDetails 的具體實現類,當然用戶也可以自行實現 UserDetails 接口。

  7. 同6
  8.  如果用戶鑒權成功,則返回Authentication對象,相比於傳入的未鑒權的對象,這個鑒權后的的對象更“豐滿”,包含了用戶的角色信息

    

從上圖可以看出,鑒權成功的Authentication對象(Fully populated Authentication Object)包含:

  authenticated- true

  grant authorities list :關聯的角色(角色和權限掛鈎)

  user credentials:用戶憑證(僅僅包含用戶名)

如果鑒權未通過,則拋出異常 AuthenticationException 。該異常屬於運行時異常,不期望用戶通過try/catch去處理,spring security提供了一種通用的方式。即通過AuthenticationEntryPoint 處理:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .exceptionHandling()
            .authenticationEntryPoint(unauthorizedHandler);
    }

  9. Authentication is done! 鑒權成功后,AuthenticationManager返回包含完整信息的鑒權對象給相關的Authentication Filter。

  10. 將返回的鑒權對象保存到SecurityContext,用於后續過濾器的使用。比如Authorization Filters   

SecurityContextHolder.getContext().setAuthentication(authentication);

  

 Reference

https://springbootdev.com/2017/08/23/spring-security-authentication-architecture/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM