使用Spring Security未找到AuthenticationProvider [英] No AuthenticationProvider found using spring security

查看:451
本文介绍了使用Spring Security未找到AuthenticationProvider的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试使用他们的x509证书通过LDAP对用户进行身份验证,但似乎无法使其正常运行.我已经声明了一个身份验证提供程序,但仍然收到错误消息,说没有提供程序.

I have been trying to authenticate a user via LDAP using their x509 certificate and cannot seem to get it working. I have an authentication provider declared, but I am still getting an error thrown saying there is no provider.

这是我的调试输出:

INFO: Initiating Jersey application, version 'Jersey: 1.12 02/15/2012 04:51 PM'
DEBUG: o.s.security.web.FilterChainProxy - /x509 at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
DEBUG: o.s.s.w.c.HttpSessionSecurityContextRepository - No HttpSession currently exists
DEBUG: o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created.
DEBUG: o.s.security.web.FilterChainProxy - /x509 at position 2 of 8 in additional filter chain; firing Filter: 'customX509AuthenticationFilter'
DEBUG: m.d.CustomX509AuthenticationFilter - Checking secure context token: null
DEBUG: m.d.CustomX509AuthenticationFilter - X.509 client authentication certificate: [removed to save space]
DEBUG: m.d.CustomX509PrincipalExtractor - Subject DN is 'CN=Last.First.M.1234567890, OU=GROUP1, O=ORG, C=US'
DEBUG: m.d.CustomX509PrincipalExtractor - Extracted Principal name is '1234567890'
DEBUG: m.d.CustomX509AuthenticationFilter - X.509 client authentication certificate: [removed to save space]
DEBUG: m.d.CustomX509AuthenticationFilter - preAuthenticatedPrincipal = 1234567890, trying to authenticate
DEBUG: m.d.CustomX509AuthenticationFilter - Cleared security context due to exception
org.springframework.security.authentication.ProviderNotFoundException: No AuthenticationProvider found for org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:196) ~[spring-security-core-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doAuthenticate(AbstractPreAuthenticatedProcessingFilter.java:115) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doFilter(AbstractPreAuthenticatedProcessingFilter.java:85) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:184) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:155) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259) [spring-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) [catalina.jar:6.0.29]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:6.0.29]
    at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:205) [cors-filter-1.3.2.jar:na]
    at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:266) [cors-filter-1.3.2.jar:na]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) [catalina.jar:6.0.29]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:6.0.29]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) [catalina.jar:6.0.29]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) [catalina.jar:6.0.29]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) [catalina.jar:6.0.29]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [catalina.jar:6.0.29]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [catalina.jar:6.0.29]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298) [catalina.jar:6.0.29]
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857) [tomcat-coyote.jar:6.0.29]
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588) [tomcat-coyote.jar:6.0.29]
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) [tomcat-coyote.jar:6.0.29]
    at java.lang.Thread.run(Thread.java:679) [na:1.6.0_22]
DEBUG: o.s.security.web.FilterChainProxy - /x509 at position 3 of 8 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
DEBUG: o.s.security.web.FilterChainProxy - /x509 at position 4 of 8 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
DEBUG: o.s.security.web.FilterChainProxy - /x509 at position 5 of 8 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
DEBUG: o.s.s.w.a.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
DEBUG: o.s.security.web.FilterChainProxy - /x509 at position 6 of 8 in additional filter chain; firing Filter: 'SessionManagementFilter'
DEBUG: o.s.s.w.s.SessionManagementFilter - Requested session ID E34E30E0411B02EFA37B41BCBA282041 is invalid.
DEBUG: o.s.security.web.FilterChainProxy - /x509 at position 7 of 8 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
DEBUG: o.s.security.web.FilterChainProxy - /x509 at position 8 of 8 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
DEBUG: o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /x509; Attributes: [hasRole('user')]
DEBUG: o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
DEBUG: o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@6b207925, returned: -1
DEBUG: o.s.s.w.a.ExceptionTranslationFilter - Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83) ~[spring-security-core-3.1.1.RELEASE.jar:3.1.1.RELEASE]
    ...

DEBUG: o.s.s.w.s.HttpSessionRequestCache - DefaultSavedRequest added to Session: DefaultSavedRequest[https://192.168.56.67/cert/x509]
DEBUG: o.s.s.w.a.ExceptionTranslationFilter - Calling Authentication entry point.
DEBUG: o.s.s.w.a.Http403ForbiddenEntryPoint - Pre-authenticated entry point called. Rejecting access
DEBUG: o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
DEBUG: o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed

这是我的spring-security.xml:

Here is my spring-security.xml:

<http entry-point-ref="http403" use-expressions="true">
    <intercept-url pattern="/**" access="hasRole('user')" />
    <custom-filter position="PRE_AUTH_FILTER" ref="x509Filter" />
</http>

<global-method-security secured-annotations="enabled" />

<authentication-manager alias="authManager">
    <authentication-provider ref="daoAuthenticationProvider" />
</authentication-manager>

<beans:bean id="http403" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />

<beans:bean id="x509Filter" class="CustomX509AuthenticationFilter">
    <beans:property name="authenticationManager" ref="authManager" />
    <beans:property name="principalExtractor">
        <beans:bean class="CustomX509PrincipalExtractor" />
    </beans:property>
</beans:bean>

<beans:bean id="daoAuthenticationProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
    <beans:constructor-arg>
        <beans:ref bean="authenticator" />
    </beans:constructor-arg>
    <beans:constructor-arg>
        <beans:ref local="populator" />
    </beans:constructor-arg>
    <beans:property name="hideUserNotFoundExceptions" value="false" />
</beans:bean>

<beans:bean id="authenticator" class="org.springframework.security.ldap.authentication.BindAuthenticator">
    <beans:constructor-arg>
      <beans:ref local="contextSource" />
    </beans:constructor-arg>
    <beans:property name="userSearch">
      <beans:ref local="userSearch" />
    </beans:property>
 </beans:bean>

<beans:bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
    <beans:constructor-arg value="ldap://localhost:389/dc=my,dc=domain" />
    <beans:property name="userDn" value="cn=manager,dc=my,dc=domain" />
    <beans:property name="password" value="password" />
</beans:bean>

<beans:bean id="populator" class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
    <beans:constructor-arg index="0">
        <beans:ref local="contextSource" />
    </beans:constructor-arg>
    <beans:constructor-arg index="1" value="ou=roles" />
    <beans:property name="groupRoleAttribute" value="cn" />
    <beans:property name="groupSearchFilter" value="(member={0})" />
    <beans:property name="rolePrefix" value="none" />
    <beans:property name="convertToUpperCase" value="false" />
    <beans:property name="searchSubtree" value="false" />
</beans:bean>

<beans:bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
    <beans:constructor-arg index="0" value="ou=people" />
    <beans:constructor-arg index="1" value="(uid={0})" />
    <beans:constructor-arg index="2">
        <beans:ref local="contextSource" />
    </beans:constructor-arg>
</beans:bean>

<beans:bean id="userDetailsService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService">
    <beans:constructor-arg>
        <beans:ref local="userSearch" />
    </beans:constructor-arg>
    <beans:constructor-arg>
        <beans:ref local="populator" />
    </beans:constructor-arg>
</beans:bean>

我无法弄清楚为什么会引发该错误,并且已经做了很多研究以试图找出问题的根源.任何帮助将不胜感激.

I cannot figure out why the error is being thrown and have done a lot of research trying to get to the root of the problem. Any help would be greatly appreciated.

谢谢, 詹姆斯

推荐答案

从技术上讲,问题在于您的身份验证过滤器与身份验证提供程序不兼容:您的CustomX509AuthenticationFilter创建一个PreAuthenticatedAuthenticationToken,并将其发送到配置为要处理的LdapAuthenticationProvider,但是该提供程序仅支持UsernamePasswordAuthenticationToken.

At a techical level the problem is that your authentication filter is incompatible with your authentication provider: your CustomX509AuthenticationFilter creates a PreAuthenticatedAuthenticationToken, and sends it to the configured LdapAuthenticationProvider to be processed, but that provider only supports UsernamePasswordAuthenticationTokens.

您也许可以通过使您的CustomX509AuthenticationFilter创建一个UsernamePasswordAuthenticationToken来解决问题,但是我想这里似乎存在一些概念上的问题.

You might be able to solve the problem by making your CustomX509AuthenticationFilter create a UsernamePasswordAuthenticationToken instead, but there seems to be some conceptual problem here, I guess.

如果客户端提供了有效的x509证书,您是否应该不经过进一步LDAP身份验证就信任它?即使您希望执行此附加步骤,您从何处获取LDAP绑定操作的密码?您是否从证书中提取出来?如果是这样,这将不会为您提供任何额外的安全性,因为如果某人拥有证书,无论使用或不使用LDAP,无论如何他们都将通过身份验证.

If a client provides a valid x509 certificate shouldn't you just trust it without further LDAP authentication? Even if you wanted this additional step, where do you get the password for the LDAP bind operation? Do you extract that from the certificate? If so, this won't give you any additional security, because if someone has the certificate, they will get authenticated anyway with or without LDAP.

在James发表评论后更新:

看来,LDAP所需的只是证书所标识用户的角色信息,在这种情况下,您无需根据LDAP对其进行身份验证.您只需要使用contextSource中已配置的LDAP管理器帐户来加载用户详细信息.请尝试以下操作:

It seems that all you need from LDAP is role information for the user identified by the certificate, in which case you don't need to authenticate it against LDAP. You only need to load user details using the LDAP manager account already configured in your contextSource. Try the following:

  1. LdapUserDetailsService包裹在UserDetailsByNameServiceWrapper
  2. 代替LdapAuthenticationProvider来配置PreAuthenticatedAuthenticationProvider,它将能够处理由CustomX509AuthenticationFilter发出的PreAuthenticatedAuthenticationToken.
  3. 将包裹的LdapUserDetailsService注入到PreAuthenticatedAuthenticationProvider中.
  1. Wrap your LdapUserDetailsService in a UserDetailsByNameServiceWrapper
  2. Instead of the LdapAuthenticationProvider configure a PreAuthenticatedAuthenticationProvider that will be able to process the PreAuthenticatedAuthenticationToken issued by your CustomX509AuthenticationFilter.
  3. Inject the wrapped LdapUserDetailsService into the PreAuthenticatedAuthenticationProvider.

这将确保使用来自LDAP的所有可用信息填充Authentication对象.然后,后续的过滤器可以根据用户授予的权限(LDAP中定义的组成员身份)来授权请求​​.

This will make sure that the Authentication object gets populated with all information available from LDAP. Then subsequent filters can authorize the request based on the user's granted authorities (group memberships defined in LDAP).

这篇关于使用Spring Security未找到AuthenticationProvider的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆