2009-08-24 165 views
16

我正在嘗試在我的web應用程序中集成Spring Security。只要整合認證和授權的整個過程,看起來很容易。spring-security:無認證的授權

但是,身份驗證和授權看起來非常耦合,因此我瞭解如何分割這些進程並獲取與授權無關的身份驗證非常耗時。

身份驗證過程在我們的系統外部(基於單點登錄),無法修改。不過,一旦用戶成功完成此過程,它將加載到會話中,包括角色。

我們試圖實現的是將這些信息用於Spring Security的授權過程,也就是說,強制它從用戶會話中獲取角色,而不是通過身份驗證提供程序。

有什麼辦法可以達到這個目的嗎?

+0

我更新了我的答案。 – 2009-08-24 18:01:40

回答

18

如果您的身份驗證已使用SSO服務完成,那麼您應該使用spring security的pre-authentication filters之一。然後,你可以指定一個UserDetails服務(可能爲自定義),將使用預認證的用戶原則來填充的GrantedAuthority的

SpringSecurity包括幾個預認證過濾器,包括J2eePreAuthenticatedProcessingFilter和RequestHeaderPreAuthenticatedProcessingFilter。如果你找不到一個適合你的工具,那麼它也是可能的,而且你自己也不難編寫,只要你知道請求中的SSO實現填充數據的位置。 (這取決於課程的實施。)

只需實現Filter接口做這樣的事情在doFilter方法:

public void doFilter(ServletRequest request, ServletResponse response, 
      FilterChain chain) throws IOException, ServletException { 

    // principal is set in here as a header or parameter. you need to find out 
    // what it's named to extract it 
    HttpServletRequest req = (HttpServletRequest) request; 

    if (SecurityContextHolder.getContext().getAuthentication() == null) { 
     // in here, get your principal, and populate the auth object with 
     // the right authorities 
     Authentication auth = doAuthentication(req); 
     SecurityContextHolder.getContext().setAuthentication(auth); 
    } 

    chain.doFilter(request, response); 
} 
+0

您好,我一直在努力。你的回答非常有幫助,但現在我不得不推遲這個問題幾天。我會回到它並讓你知道事情是怎麼回事。謝謝! – markitus82 2009-08-26 06:57:11

+0

您的歡迎。祝你好運! – nont 2009-08-26 13:28:26

+0

這對於我們的應用程序來說還不夠...我還需要將SecurityContext添加到會話中,如下所示:session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,SecurityContextHolder.getContext()); – 2013-05-22 22:42:32

3

是的,這是可能的。 Spring Security(與Spring的大部分其他部分一樣)是接口驅動的,這樣你就可以爲框架的不同部分有選擇地插入自己的實現。

更新: Spring的授權和認證機制一起工作 - 身份驗證機制將認證用戶,並在安全範圍內插入各種GrantedAuthority實例。這些將由授權機構檢查以允許/禁止某些操作。

有關如何使用預先存在的身份驗證的詳細信息,請使用nont的答案。您如何從會話中獲得詳細信息(例如角色)的詳細信息當然取決於您的具體設置。但是,如果您將由您的SSO系統中的預填充角色派生的GrantedAuthority實例放入您的授權邏輯中,您將能夠使用它們。

從參考文檔(稍微改動過,與我的重點):

你可以(而且很多用戶)寫 自己的過濾器或MVC控制器 提供與不是 認證系統的互操作性基於Spring Security的 。例如, 您可能正在使用Container Managed 認證,這使得當前的 用戶可以從ThreadLocalJNDI位置獲得。 或者您可能爲擁有舊版專有 身份驗證系統的 公司工作,該公司「 」 對其無法控制。在這樣的 的情況下,很容易獲得 Spring Security的工作,並且仍然 提供授權功能。 所有你需要做的是寫一個過濾器 (或同等學歷),讀取從 位置 第三方用戶信息,建立一個春天 安全專用Authentication 對象,並把它放到 SecurityContextHolder。 這樣做很容易,而且這是一個完全支持的集成方法。

+0

但有必要配置一個AuthenticationProvider? – markitus82 2009-08-24 13:21:22

+0

是的,但不必是授權提供者的另一個對象:您可以創建一個實現兩者的類(因爲您的SSO系統似乎也給予了這兩者)。 – 2009-08-24 13:35:04

+0

事情是,我的應用程序中的登錄表單(身份驗證)是由外部系統執行的。我所擁有的僅僅是用戶會話,並且用戶已經通過身份驗證。我想知道如何從會話中獲取userId和角色以使用Spring授權。 – markitus82 2009-08-24 13:43:51

2

處理認證的服務器應該將用戶重定向到傳遞給它的某種類型的密鑰(CAS SSO中的一個令牌)的應用程序。然後,應用程序使用該密鑰向認證服務器詢問關聯的用戶名和角色。通過此信息創建傳遞給授權管理器的安全上下文。這是SSO登錄工作流程的一個非常簡化的版本。看看CAS SSOCAS 2 Architecture
如果您需要更多信息,告訴我。

1

我想了解我們自己的授權CAS認證,並在此認證我還添加源代碼和測試用例的詳細信息因爲Spring Security中的User對象總是希望填充密碼,我們並不關心我們的場景。在閱讀Surabh的帖子後,似乎訣竅是返回一個自定義的User對象,但沒有填入密碼。我會試試看看它是否適用於我的情況。希望鏈中的其他代碼不會期待用戶對象中的密碼。

1

我該使用授權:

  1. 注入授權相關Bean到我自己的bean:

    @Autowired 
    private AccessDecisionManager accessDecisionManager; 
    @Autowired 
    FilterSecurityInterceptor  filterSecurityInterceptor; 
    
  2. 使用這個bean通過這樣的:

    FilterInvocation fi = new FilterInvocation(rundata.getRequest(), rundata.getResponse(), new FilterChain() { 
    
        public void doFilter(ServletRequest arg0, ServletResponse arg1) throws IOException, ServletException { 
         // TODO Auto-generated method stub 
    
        } 
    }); 
    FilterInvocationDefinitionSource objectDefinitionSource = filterSecurityInterceptor.getObjectDefinitionSource(); 
    ConfigAttributeDefinition attr = objectDefinitionSource.getAttributes(fi); 
    Authentication authenticated = new Authentication() { 
    
        ........... 
    
        public GrantedAuthority[] getAuthorities() { 
         GrantedAuthority[] result = new GrantedAuthority[1]; 
         result[0] = new GrantedAuthorityImpl("ROLE_USER"); 
         return result; 
        } 
    }; 
    accessDecisionManager.decide(authenticated, fi, attr);