我们正在构建一个可供经过身份验证的用户和匿名用户使用的Web应用程序。如果您决定不注册/登录,则只有一组有限的功能。使用Spring Security通过OpenID完成用户身份验证。这很好。
但是,该应用程序还附带了一个部署在<host>/<context-root>/admin
的管理UI。我们可以在Spring Security中有两个独立的领域(例如/admin/**
的基本身份验证)吗?如何配置?
答案 0 :(得分:18)
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>
需要注意的关键是第一个pattern="/admin/**"
元素上的http
。这告诉Spring /admin
下的所有网址都属于该领域而不是默认领域 - 因此/admin
下的网址会使用基本身份验证。
答案 1 :(得分:1)
可能的解决方案:
/admin
添加URL拦截器,需要“ROLE_ADMIN”org.springframework.security.web.authentication.www.BasicAuthenticationFilter
的实例以截取/admin
网址,并在用户提供相应凭据时将其验证为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的默认实现是一个被动过滤器,即它只是在请求中查找基本的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"));
}
}
}
此外,您需要调整过滤器以仅应用于/admin
网址 - 通过在doFilter
方法中进行硬编码或提供适当的包装bean。
答案 2 :(得分:0)
我想不出有两个领域的直接方式(我自己也没试过):
您可以定义两个过滤器in your web.xml,其中每个过滤器具有不同的弹簧配置并且可以自行设置环境。全局事物进入app配置,过滤器配置中的域特定。
如果只是针对不同的身份验证方法,您可以write your own filter然后决定调用哪个过滤器。