PreAuthenticatedAuthenticationProvider UsernameNotFound异常返回401而不是拒绝页面

时间:2015-07-14 08:57:29

标签: java spring spring-security

我使用spring 4.1.6.RELEASE和spring-security 4.0.1.RELEASE。

有RequestHeaderAuthenticationFilter和PreAuthenticatedAuthenticationProvider。如果用户服务抛出UsernameNotFoundException,我希望我的应用程序显示“已拒绝”页面。 实际上,应用程序显示基本的HTTP授权表单(凭据的简单浏览器弹出窗口),如果取消则提供401响应。

这是我的配置:

<s:http auto-config="true" use-expressions="true">
    <s:intercept-url pattern="/report/**" access="hasRole('ROLE_USER')"/>
    <s:csrf disabled="true"/>
    <s:custom-filter ref="preAuthFilter" position="PRE_AUTH_FILTER"/>
    <s:form-login
            authentication-failure-url="/denied.jsp"/>
</s:http>

<b:bean id="preAuthFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
    <b:property name="principalRequestHeader" value="REMOTE_USER"/>
    <b:property name="authenticationManager" ref="authManager"/>
</b:bean>

<s:authentication-manager id="authManager">
    <s:authentication-provider user-service-ref="userDetailsService"/>
</s:authentication-manager>

<b:bean id="userDetailsService" class="com.db.dump.tool.security.UserDetailsServiceImpl"/>

类UserDetailsS​​erviceImpl只检查具有DB的用户,如果找不到用户则抛出UsernameNotFoundException。也许这是一个问题? 请建议。

提前致谢, 亚历

2 个答案:

答案 0 :(得分:1)

此行为是由于ExceptionTranslationFilter将最终异常翻译为:

  

拒绝访问(用户是匿名的);重定向到身份验证入口点

用户是匿名的,因为您的UserDetailsS​​ervice引发了异常。您正在获得401响应,因为它已在BasicAuthenticationEntryPoint中以这种方式实现,在具有匿名用户主体的非XMLHttpRequest(您的情况)的情况下,它充当身份验证入口点。

如果您希望显示拒绝访问页面(不允许匿名用户进行身份验证),您需要使用http元素上的entry-point-ref属性插入您自己的AuthenticationEntryPoint(然后也可以让AccessDeniedHandler进入图片)。由此产生的影响看起来像这样:

import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;

public class CustomAuthEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
        AuthenticationException authException) throws IOException, ServletException {
        response.setStatus(SC_FORBIDDEN); /* You can also call an access denied handler here and let it handle some meaningful exception that you pass into the handle method. */
    }
}

PS:当然,在开始工作之前,您需要将新的身份验证入口点配置为spring bean。

答案 1 :(得分:0)

我发现的解决方案是不为用户设置权限,也不抛出任何异常。在这种情况下,我们有403错误页面,可以通过access-denied-handler定制。

相关问题