我使用 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"/>
类 UserDetailsServiceImpl 仅使用数据库检查用户,如果未找到用户,则抛出 UsernameNotFoundException。也许这里有问题? 敬请指教。
提前致谢, 亚历克斯
最佳答案
此行为是由于 ExceptionTranslationFilter 将最终异常转换为:
Access is denied (user is anonymous); redirecting to authentication entry point
用户是匿名的,因为您的 UserDetailsService 引发了异常。您收到 401 响应,因为它已在 BasicAuthenticationEntryPoint 中以这种方式实现在具有匿名用户主体的非 XMLHttpRequest(您的情况)的情况下,它充当身份验证入口点。
如果您希望显示拒绝访问页面(不给匿名用户进行身份验证的机会),则需要插入您自己的 AuthenticationEntryPoint使用http元素上的entry-point-ref属性(然后也可以让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。
关于java - PreAuthenticatedAuthenticationProvider UsernameNotFound 异常返回 401 而不是拒绝页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31402141/