【发布时间】:2015-11-21 09:22:57
【问题描述】:
在我使用 Spring Security 保护的 Spring MVC 应用程序中,我必须使用多种登录方式:一种是通过识别特定授权 IP 列表(不需要用户/密码登录),另一种是通过经典登录。为此,我构建了一个自定义身份验证提供程序来验证 IP 是否被授权。如果不是,我希望它重定向到通知用户的错误页面。
在这种情况下,我会抛出异常 (org.springframework.security.authentication.InsufficientAuthenticationException),我正在尝试使用 ExceptionMappingAuthenticationFailureHandler 来捕获它并重定向到正确的页面。失败处理程序将InsufficientAuthenticationException 映射到该页面,并将BadCredentialsException 映射到另一个错误页面(在执行经典用户/密码登录并且登录错误时使用)。
我检查了我实际上是在抛出异常的日志。但是,故障处理程序永远不会捕获它;相反,我总是得到用于BadCredentialsException 的页面。
如何确保我抛出的异常被失败处理程序捕获?
这是我的 security-context.xml 的摘录:
<http
auto-config="true"
use-expressions="true">
<form-login
login-page="/pages/login.jsp"
login-processing-url="/j_spring_security_check"
default-target-url="/"
authentication-failure-handler-ref="authenticationFailureHandler" />
</http>
<beans:bean
id="customIPAddressAuthenticationProvider"
class="ch.of.ow.security.CustomIPAddressAuthenticationProvider" />
<beans:bean
id="authenticationFailureHandler"
class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
<beans:property name="exceptionMappings">
<beans:props>
<beans:prop
key="org.springframework.security.authentication.InsufficientAuthenticationException">
/notValidIP
</beans:prop> <!-- THIS IS THE PAGE I WANT -->
<beans:prop
key="org.springframework.security.authentication.BadCredentialsException">
/pages/login.jsp?login_error=true
</beans:prop> <!-- THIS IS THE PAGE I GET INSTEAD -->
</beans:props>
</beans:property>
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="customIPAddressAuthenticationProvider" />
<authentication-provider user-service-ref='userDetailsService'>
<password-encoder hash="bcrypt" />
</authentication-provider>
</authentication-manager>
这里是 CustomIPAddressAuthenticationProvider 的相关部分:
public class CustomIPAddressAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException, InsufficientAuthenticationException {
if (!authentication.getPrincipal().equals("") || !authentication.getCredentials().equals("")) {
// if the user did provide a username/password, skip to the next
// authentication provider, as he will want to log in with his
// credentials instead of his IP
return null;
}
WebAuthenticationDetails wad = null;
String userIPAddress = null;
boolean isAuthenticatedByIP = false;
// Get the IP address of the user tyring to use the site
wad = (WebAuthenticationDetails) authentication.getDetails();
userIPAddress = wad.getRemoteAddress();
// Check if the user is authorized
isAuthenticatedByIP = ipIsAuthorized(userIPAddress); //the ipIsAuthorized does its stuff well
// Authenticated, the user's IP address is authorized
if (isAuthenticatedByIP) {
List<GrantedAuthority> grantedAuths = new ArrayList<>();
grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
Authentication result = new UsernamePasswordAuthenticationToken("xxxxxxxxx", "yyyyyyyyy", grantedAuths);
return result;
} else {
System.out.println("Going to throw InsufficientAuthenticationException");
throw new InsufficientAuthenticationException(userIPAddress);
}
}
}
我还注意到,如果我删除了失败处理程序的第二个映射,我只留下了:
<beans:prop
key="org.springframework.security.authentication.InsufficientAuthenticationException">
/notValidIP
</beans:prop>
然后我看到,如果我尝试使用不受信任的 IP 进行访问,我会收到来自 /j_spring_security_check 的 HTTP Status 401 - Authentication Failed: Bad credentials。所以这确实是个例外。我可能把我的异常扔错了地方吗?在身份验证提供程序中抛出异常是否意味着触发链中更高级别的错误凭据异常?
提前感谢您提供的任何建议。
【问题讨论】:
标签: java spring spring-mvc authentication spring-security