java 使用 Spring Security 的同一应用程序中的两个领域?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3671861/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Two realms in same application with Spring Security?
提问by Marcel St?r
We're building a web application that is available to both authenticated and anonymous users. If you decide not to register/login you only have a limited set of features. User authentication is done over OpenID with Spring Security. That works fine.
我们正在构建一个可供经过身份验证的用户和匿名用户使用的 Web 应用程序。如果您决定不注册/登录,您只能使用有限的一组功能。用户身份验证是通过 OpenID 使用 Spring Security 完成的。这很好用。
However, the application also comes with an admin UI that is deployed at <host>/<context-root>/admin
. Can we have two separate realms with Spring Security (e.g. basic auth for /admin/**
)? How does that have to be configured?
但是,该应用程序还带有一个部署在<host>/<context-root>/admin
. 我们可以使用 Spring Security 拥有两个独立的领域(例如,基本身份验证/admin/**
)吗?那必须如何配置?
回答by gutch
Spring Security has added support for this scenario in version 3.1, which is currently available as a Release Candidate. It was implemented by SEC-1171and details of the syntax are in the manual included with 3.1.
Spring Security 在版本 3.1 中添加了对这种场景的支持,该版本目前可作为候选发布版本。它是由SEC-1171实现的,语法的详细信息在 3.1 附带的手册中。
However it's pretty simple to use. Basically you just define multiple http
elements in your Spring Security configuration, one for each realm. We're using it like this:
但是它使用起来非常简单。基本上,您只需http
在 Spring Security 配置中定义多个元素,每个领域一个。我们像这样使用它:
<!-- 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>
The key thing to note is the pattern="/admin/**"
on the first http
element. This tells Spring that all URLs under /admin
are subject to that realm instead of the default realm — and thus URLs under /admin
use basic authentication instead.
要注意的关键是pattern="/admin/**"
第一个http
元素上的 。这告诉 Spring 下的所有 URL/admin
都受该领域而不是默认领域的约束——因此下的 URL/admin
使用基本身份验证。
回答by Boris Kirzner
Possible solution:
可能的解决方案:
- Add URL interceptor for
/admin
the requires "ROLE_ADMIN" - Configure instance of
org.springframework.security.web.authentication.www.BasicAuthenticationFilter
to intercept the/admin
URL and authenticate user as ROLE_ADMIN if it provides the appropriate credentials
- 为
/admin
需要“ROLE_ADMIN”添加 URL 拦截器 - 配置实例
org.springframework.security.web.authentication.www.BasicAuthenticationFilter
以拦截/admin
URL 并将用户身份验证为 ROLE_ADMIN 如果它提供适当的凭据
Sample configuration:
示例配置:
<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>
Note: default implementation of BasicAuthenticationFilter is a passive filter, i.e. it just looks for a basic auth header in the request and if it is not present - does nothing. If you want the filter to explicitly require the basic authentication from the client, you need to extend the default implementation to commence to authentication entry point:
注意: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"));
}
}
}
In addition, you need to tweak the filter to apply to /admin
URL only - either by hard-coding this in doFilter
method or by providing an appropriate wrapper bean.
此外,您需要调整过滤器以仅应用于/admin
URL - 通过在doFilter
方法中对此进行硬编码或通过提供适当的包装 bean。
回答by dube
I can't think of a straight forward way to have two realms (and I didn't try it myself):
我想不出有两个领域的直接方法(我自己也没有尝试过):
you may define two filters in your web.xmlwhere each of those has a different spring configuration and ergo an own environment. The global things go into the app config, the realm-specific in the filter config.
您可以在您的 web.xml中定义两个过滤器,其中每个过滤器都有不同的 spring 配置并因此有自己的环境。全局事物进入应用程序配置,过滤器配置中特定于领域的内容。
if it's only for a different auth method, you could write your own filterwhich then decides which filter to call.
如果它仅用于不同的身份验证方法,您可以编写自己的过滤器,然后决定调用哪个过滤器。