与Spring Security在同一应用程序中的两个领域?

2022-09-02 21:53:19

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

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


答案 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>

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


答案 2

可能的解决方案:

  • 为所需的“ROLE_ADMIN”添加 URL 拦截器/admin
  • 将 的实例配置为截获 URL 并将用户身份验证为ROLE_ADMIN(如果用户提供适当的凭据)org.springframework.security.web.authentication.www.BasicAuthenticationFilter/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的默认实现是一个被动过滤器,即它只是在请求中查找一个基本的auth标头,如果它不存在 - 什么都不做。如果希望筛选器显式要求从客户端进行基本身份验证,则需要扩展默认实现以开始到身份验证入口点:

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

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