自定义身份验证提供程序未被调用 Spring 安全

Custom Authentication Provider is not getting called Spring Security

我正在尝试实现自定义 AuthenticationProvider 来验证对我所有受保护的 URL 的调用。我已经实现了所有方法并相信我的 xml 配置是正确的,但是对受保护 URL 的调用总是转到入口点引用 class(我在此处抛出 401 错误)。这正在跳过我的身份验证提供程序(我的身份验证方法中有日志语句并且知道它没有被调用)。从其他帖子我了解到 supports 方法可能是罪魁祸首,但我将其设置为始终 return true 所以这不应该是我的问题。

我的安全上下文代码:

    <?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <security:http 
            use-expressions="true"
            auto-config="false"
            create-session="stateless"
            entry-point-ref="unauthorizedEntryPoint"
            authentication-manager-ref="authenticationManager">
        <security:intercept-url pattern="/User/sign_up/*" access="permitAll" />
        <security:intercept-url pattern="/User/authenticate/**" access="permitAll" />
        <security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
    </security:http>

    <authentication-manager alias="authenticationManager">
        <authentication-provider ref="customAuthenticationProvider" />
    </authentication-manager>

    <beans:bean id="customAuthenticationProvider" class="pathto:CustomAuthenticationProvider" />

    <beans:bean id="unauthorizedEntryPoint" class="pathto:UnauthorizedEntryPoint" /

web.xml的代码:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    The definition of the Root Spring Container shared by all Servlets and Filters -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/security-context.xml
        </param-value>
    </context-param>

    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

未经授权的入口点:

public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authenticationException) throws IOException, ServletException {
        System.out.println("in unauth");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failure: UnauthorizedEntryPoint Token invalid");
    }

}

AuthenticationProvider:(当前未在此处进行任何身份验证)

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Override
    public Authentication authenticate(Authentication auth)
            throws AuthenticationException {
        System.out.println("in authenticate");
        String username = auth.getName();
        String password = auth.getCredentials().toString();
        List<GrantedAuthority> AUTHORITIES = new ArrayList<GrantedAuthority>();
        System.out.println("username: "+username+". password: "+ password);
        if (true) { //checkPassword(password, user.getPasswords())) {
            AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER"));
            return new UsernamePasswordAuthenticationToken(auth.getName(), auth.getCredentials(), AUTHORITIES);
        }
        return null;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }

更新: 我正在使用 Advanced Rest Client 使用参数 j_username 和 j_password 对此进行测试。这是正确的还是问题所在?

您是否了解可能出现的问题?

谢谢!

为什么不删除 security:http 下的 authentication-manager-ref?您已经声明了 authentication-manager 标签。

<security:http 
        use-expressions="true"
        auto-config="false"
        create-session="stateless"
        entry-point-ref="unauthorizedEntryPoint">
    <security:intercept-url pattern="/User/sign_up/**" access="permitAll" />
    <security:intercept-url pattern="/User/authenticate/**" access="permitAll" />
    <security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
</security:http>

此外;不是你问题的一部分,只是建议:

@Override
public boolean supports(Class<?> authentication) {
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
}

您没有配置 Web 身份验证机制,因此无法调用身份验证管理器。因此,请求总是会到达您的身份验证入口点(为未经身份验证的用户调用)并且您会收到观察到的错误。通常,身份验证入口点会做一些事情,比如重定向到登录表单,或发送 WWW-Authenticate header.

您需要配置表单或基本身份验证之类的东西(请参阅手册或项目附带的示例)。请注意,您还将应用程序配置为无状态,因此每个请求都需要进行身份验证。