因为要在登陆的时候增加企业编号验证,自己定义了DisUsernamePasswordAuthenticationFilter类并继承AbstractAuthenticationProcessingFilter这个类,但是运行后发现只要用户名密码错误或者没有权限等其他错误都返回401 -Authentication Failed,如下图:
后经过排查发现,在重写AbstractAuthenticationProcessingFilter类时没有传入登录失败跳转的路径failureUrl.找到问题后我在AbstractAuthenticationProcessingFilter发现该类定义了AuthenticationSuccessHandler和AuthenticationFailureHandler,所以我们可以在application-security.xml中定义一下代码:
<beans:bean id="simpleUrlAuthenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFai lureHandler"> <!-- 可以配置相应的跳转方式。属性forwardToDestination为true采用forward false为sen dRedirect --> <beans:property name="defaultFailureUrl" value="/login.jsp?auth-failure=true"></b eans:property> </beans:bean>
并在自定义的DisUsernamePasswordAuthenticationFilter类中引入
<!-- 登录处理Filter --> <beans:bean id="loginProcessFilter" class="com.fpi.safety.common.security.DisUsername PasswordAuthenticationFilter"> <beans:property name="companyCode" value="companyCode" /> <beans:property name="usernameParameter" value="username" /> <beans:property name="passwordParameter" value="password" /> <!-- 登陆失败处理类 --> <beans:property name="simpleUrlAuthenticationFailureHandler" ref="simpleUrlAuthen ticationFailureHandler" /> <beans:property name="authenticationSuccessHandler" ref="appSessionSuccessHandler " /> <beans:property name="authenticationManager" ref="disuserAuthManager" /> </beans:bean>
DisUsernamePasswordAuthenticationFilter.java
public class DisUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
public static final String SPRING_SECURITY_FORM_COMPANY_CODE_KEY = "company_code";
public static final String USERNAME_LOGINID_SPLIT = "-";
/**
* @deprecated If you want to retain the username, cache it in a customized {@code AuthenticationFailureHandler}
*/
@Deprecated
public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
private String companyCode = SPRING_SECURITY_FORM_COMPANY_CODE_KEY;
private SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler;
private boolean postOnly = true;
//~ Constructors ===================================================================================================
public DisUsernamePasswordAuthenticationFilter() {
super("/j_spring_security_check");
}
//~ Methods ========================================================================================================
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
String password = obtainPassword(request);
String companyCode = obtainCompanyCode(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
if(companyCode == null || companyCode.equals("")){
companyCode = "null";
}
username = username.trim();
companyCode = companyCode.trim();
username = username+USERNAME_LOGINID_SPLIT+companyCode;
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
protected String obtainCompanyCode(HttpServletRequest request) {
return request.getParameter(companyCode);
}
/**
* Enables subclasses to override the composition of the password, such as by including additional values
* and a separator.<p>This might be used for example if a postcode/zipcode was required in addition to the
* password. A delimiter such as a pipe (|) should be used to separate the password and extended value(s). The
* <code>AuthenticationDao</code> will need to generate the expected password in a corresponding manner.</p>
*
* @param request so that request attributes can be retrieved
*
* @return the password that will be presented in the <code>Authentication</code> request token to the
* <code>AuthenticationManager</code>
*/
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter);
}
/**
* Enables subclasses to override the composition of the username, such as by including additional values
* and a separator.
*
* @param request so that request attributes can be retrieved
*
* @return the username that will be presented in the <code>Authentication</code> request token to the
* <code>AuthenticationManager</code>
*/
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
}
/**
* Provided so that subclasses may configure what is put into the authentication request's details
* property.
*
* @param request that an authentication request is being created for
* @param authRequest the authentication request object that should have its details set
*/
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
}
/**
* Sets the parameter name which will be used to obtain the username from the login request.
*
* @param usernameParameter the parameter name. Defaults to "j_username".
*/
public void setUsernameParameter(String usernameParameter) {
Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
this.usernameParameter = usernameParameter;
}
/**
* Sets the parameter name which will be used to obtain the password from the login request..
*
* @param passwordParameter the parameter name. Defaults to "j_password".
*/
public void setPasswordParameter(String passwordParameter) {
Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
this.passwordParameter = passwordParameter;
}
@Override
public void afterPropertiesSet() {
super.afterPropertiesSet();
/*
*该处理器实现了 AuthenticationFailureHandler
*用于处理登录失败后,跳转的界面
*/
this.setAuthenticationFailureHandler(simpleUrlAuthenticationFailureHandler);
}
/**
* Defines whether only HTTP POST requests will be allowed by this filter.
* If set to true, and an authentication request is received which is not a POST request, an exception will
* be raised immediately and authentication will not be attempted. The <tt>unsuccessfulAuthentication()</tt> method
* will be called as if handling a failed authentication.
* <p>
* Defaults to <tt>true</tt> but may be overridden by subclasses.
*/
public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
}
public final String getUsernameParameter() {
return usernameParameter;
}
public final String getPasswordParameter() {
return passwordParameter;
}
public String getCompanyCode() {
return companyCode;
}
public void setCompanyCode(String companyCode) {
this.companyCode = companyCode;
}
public SimpleUrlAuthenticationFailureHandler getSimpleUrlAuthenticationFailureHandler() {
return simpleUrlAuthenticationFailureHandler;
}
public void setSimpleUrlAuthenticationFailureHandler(
SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler) {
this.simpleUrlAuthenticationFailureHandler = simpleUrlAuthenticationFailureHandler;
}
}
这样就能使登陆错误成功返回登陆页面,问题得以解决。
转载于:https://blog.51cto.com/13095720/1968316