java Spring Security 身份验证管理器不会被自定义过滤器接收
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17127119/
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
Spring Security authentication manager won't get picked up on custom filter
提问by basvanstratum
I'm trying to create a custom filter to take care of authentication, since I'm forced to use a combination of an AD and local database (arg!) to determine access rights. I'm using the official docs, for this particular issue mostly this part.
我正在尝试创建一个自定义过滤器来处理身份验证,因为我被迫使用 AD 和本地数据库(arg!)的组合来确定访问权限。我正在使用官方文档,对于这个特定问题主要是this part。
However, when I run my server it is complaining about the AuthenticationManager being null, while I believe I am setting it in XML as covered in this SO question. What am I missing here?
但是,当我运行我的服务器时,它抱怨 AuthenticationManager 为空,而我相信我是在这个 SO question中介绍的 XML 中设置它。我在这里错过了什么?
The exception:
例外:
SEVERE: Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myUsernamePasswordAuthenticationFilter' defined in file [*snip*]:
Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: authenticationManager must be specified
...
Caused by: java.lang.IllegalArgumentException: authenticationManager must be specified
at org.springframework.util.Assert.notNull(Assert.java:112)
The XML: (with some simplified class names)
XML :(带有一些简化的类名)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<context:property-placeholder location="classpath*:META-INF/spring/*.properties" />
<context:spring-configured />
<context:component-scan base-package="myapp" />
<!-- Spring Security Configuration. -->
<sec:http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint"
access-denied-page="/denied.jsp">
<sec:custom-filter position="FORM_LOGIN_FILTER" ref="myAuthenticationFilter" />
<sec:intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<sec:intercept-url pattern="/404.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<sec:intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<sec:intercept-url pattern="/**" access="ROLE_USER" />
<sec:logout logout-url="/logout" logout-success-url="/login" />
</sec:http>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="myAuthenticationProvider" />
</sec:authentication-manager>
<bean id="loginUrlAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login" />
</bean>
<bean id="myAuthenticationFilter" class="myapp.MyUsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="myAuthenticationProvider" class="myapp.MyAuthenticationProvider" />
The Filter:
过滤器:
@Component
public class MyUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public AdminUsernamePasswordAuthenticationFilter() {
super("/login");
}
@Override
public Authentication attemptAuthentication(final HttpServletRequest request,
final HttpServletResponse response) throws AuthenticationException {
// stuff and:
return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(
login, request.getParameter("password")));
}
}
The AuthenticationProvider:
身份验证提供者:
@Component
public class MyAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
// all the funky AD+DB code
return null;
}
@Override
public boolean supports(final Class<?> clazz) {
return true;
}
}
I am running Java 6, the latest Spring Security (3.1.4.RELEASE) and Spring (3.2.3.RELEASE) versions, running on a Tomcat v6 server. Different Spring versions do not appear to be a problem (related SO question). And if it would be a problem, having to run Spring 3.1.4 if you want to use Spring Security is just meh...
我正在运行 Java 6、最新的 Spring Security (3.1.4.RELEASE) 和 Spring (3.2.3.RELEASE) 版本,在 Tomcat v6 服务器上运行。不同的 Spring 版本似乎不是问题(相关的 SO 问题)。如果这会成为一个问题,如果你想使用 Spring Security 就必须运行 Spring 3.1.4 只是meh...
Some additional things I tried to no avail:
我试图无济于事的一些其他事情:
- I tried ditching the
<sec:authentication-manager />
in favour of a normal bean, as mentioned here (bottom answer). - I tried adding bean id's, names, authentication-manager-refs in all sorts of combinations.
回答by Pavel Horal
Ah... I spot the basic error made by many in Spring. You have your bean MyUsernamePasswordAuthenticationFilter
defined in XML, which is correct. However you have it also annotated by @Component
annotation, which means it is being picked and registered as another bean definition by component scan. And bean instance comming from this definition won't indeed have its authenticationManager
dependency initalized.
啊...我发现许多人在 Spring 中犯的基本错误。您MyUsernamePasswordAuthenticationFilter
在 XML 中定义了bean ,这是正确的。但是,您还通过@Component
annotation对其进行了注释,这意味着它被component scan挑选并注册为另一个 bean 定义。来自此定义的 bean 实例确实不会authenticationManager
初始化其依赖项。
Just remove the @Component
annotation in MyUsernamePasswordAuthenticationFilter
and you should be OK.
只需删除@Component
注释MyUsernamePasswordAuthenticationFilter
就可以了。