【问题标题】:Two realms in same application with Spring Security?使用 Spring Security 在同一个应用程序中的两个领域?
【发布时间】:2011-04-09 23:14:59
【问题描述】:

我们正在构建一个可供经过身份验证的用户和匿名用户使用的 Web 应用程序。如果您决定不注册/登录,您只有一组有限的功能。使用 Spring Security 通过 OpenID 完成用户身份验证。效果很好。

但是,该应用程序还附带一个部署在 <host>/<context-root>/admin 的管理 UI。我们可以使用 Spring Security 拥有两个独立的领域(例如 /admin/** 的基本身份验证)吗?必须如何配置?

【问题讨论】:

    标签: java spring security spring-security


    【解决方案1】:

    Spring Security 在 3.1 版中增加了对这种场景的支持,目前作为候选发布版提供。它是由SEC-1171 实现的,语法的详细信息在 3.1 附带的手册中。

    不过使用起来非常简单。基本上,您只需在 Spring Security 配置中定义多个 http 元素,每个领域一个。我们是这样使用它的:

    <!-- Configure realm for system administration users -->
    <security:http pattern="/admin/**" create-session="stateless">
        <security:intercept-url pattern='/**' access='ROLE_ADMIN' requires-channel="https" />
        <security:http-basic/>  
    </security:http>
    
    
    <!-- Configure realm for standard users -->
    <security:http auto-config="true" access-denied-page="/error/noaccess" use-expressions="true" create-session="ifRequired">
        <security:form-login login-page="/login"
                ...
                ...
    </security:http>
    

    要注意的关键是第一个http 元素上的pattern="/admin/**"。这告诉 Spring /admin 下的所有 URL 都受制于该领域而不是默认领域 - 因此 /admin 下的 URL 使用基本身份验证。

    【讨论】:

    • 我一直在研究如何做到这一点,感谢您如此清楚地指出!
    • Spring security 3.1.0 已于 7/12/2011 正式发布
    • 我正在这样做,如果我登录到管理部分,我也登录到用户部分但未授权(当然)。我认为这是因为 spring security 在一个密钥下持有会话授权。有没有办法将 Spring Security 配置为您可以使用不同的授权实体同时登录到管理员和用户部分的场景?
    • 看起来访问属性的语法错误应该是:access="hasRole('ROLE_name')"
    【解决方案2】:

    可能的解决方案:

    • /admin 添加 URL 拦截器,需要“ROLE_ADMIN”
    • 配置org.springframework.security.web.authentication.www.BasicAuthenticationFilter 的实例以拦截/admin URL 并将用户身份验证为ROLE_ADMIN(如果它提供了适当的凭据)

    示例配置:

    <security:intercept-url pattern="/admin" access="ROLE_ADMIN"/>
    
    <bean id="basicAuthenticationEntryPoint" 
          class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
        <property name="realmName" 
                  value="WS realm"/>
    </bean>
    
    <bean id="basicAuthenticationProcessingFilter"
          class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
        <property name="authenticationManager" 
                  ref="authenticationManager"/>
        <property name="authenticationEntryPoint" 
                  ref="basicAuthenticationEntryPoint"/>    
    </bean>
    

    注意:BasicAuthenticationFilter 的默认实现是一个被动过滤器,即它只是在请求中查找基本身份验证标头,如果它不存在 - 什么也不做。如果您希望过滤器明确要求来自客户端的基本身份验证,则需要扩展默认实现以开始到身份验证入口点:

    public class BasicAuthenticationFilter 
           extends org.springframework.security.web.authentication.www.BasicAuthenticationFilter {
    
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    
            final HttpServletRequest request = (HttpServletRequest) req;
            final HttpServletResponse response = (HttpServletResponse) res;
    
            String header = request.getHeader("Authorization");
    
            if ((header != null) && header.startsWith("Basic ")) {
                super.doFilter(req, res, chain);
            } else {
                getAuthenticationEntryPoint().commence(request, response, new AuthenticationCredentialsNotFoundException("Missing credentials"));
            }
        }
    }
    

    此外,您需要调整过滤器以仅应用于/admin URL - 通过在doFilter 方法中对其进行硬编码或通过提供适当的包装器bean。

    【讨论】:

      【解决方案3】:

      我想不出有两个领域的直接方法(我自己也没有尝试过):

      您可以定义两个过滤器in your web.xml,其中每个过滤器都有不同的弹簧配置,因此有自己的环境。全局的东西进入应用配置,过滤器配置中的领域特定。

      如果它只是用于不同的身份验证方法,您可以write your own filter 然后决定调用哪个过滤器。

      【讨论】:

        猜你喜欢
        • 2015-10-22
        • 1970-01-01
        • 2015-08-02
        • 1970-01-01
        • 2012-07-24
        • 2017-09-19
        • 1970-01-01
        • 1970-01-01
        • 2022-08-03
        相关资源
        最近更新 更多