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);