Spring Security与Webflow和JSF重定向登录页面,没有错误消息



我正在尝试编写一个具有spring安全性的应用程序,用于JSF和wedflow上的身份验证。

以下是代码片段。

登录页面.xhtml

<h:form id="form" class="lgnfrm">
    <div id="LoginSection">
        <fieldset class="LoginBorder">
            <legend class="signin">SIGN IN</legend>
            <div>
                <div class="UsernameIcon">
                    <h:inputText id="username" maxlength="100"
                        value="#{loginCredential.loginUserId}"
                        onfocus="this.value='';"
                        requiredMessage="Please enter a username" styleClass="Width100px LoginTextbox" />                   
                </div>
                <div class="PasswordIcon">
                    <h:inputSecret id="password" maxlength="100"
                        value="#{loginCredential.password}"
                        requiredMessage="Please enter a password"
                        onfocus="this.value='';" styleClass="Width100px LoginTextbox" />                    
                </div>
                <div class="FloatLeft">
                    <h:commandButton id="loginControl" value="SIGN IN"
                        styleClass="signinButton" action="verifyCredentials" />                     
                 </div>
                <h:panelGroup rendered="#{viewScope.isLoginError == 'true'}">  
                    <h:outputText value="#{msg['auth.failure']}" />
                    <h:outputText value="Invalid Credentials!!" />
                </h:panelGroup>                
                <div class="FloatRight ForgotPWD"></div>
            </div>
        </fieldset>
    </div>  
  </h:form> 

这个流程是

login.xml

<view-state id="loginViewState" view="loginPage">
    <on-entry>
        <evaluate           
            expression="new com.iri.rpm.web.ui.beans.authentication.LoginCredential()"
            result="viewScope.loginCredential" />
    </on-entry>
    <transition on="verifyCredentials" to="validateCredentials">
        <evaluate expression="authenticationService.challengeUser(loginCredential)"
            result="flowScope.auth" />
    </transition>
</view-state>
<decision-state id="validateCredentials">
    <if test="true" then="AgentViewState"
                else="invalidCredentialsState" />
</decision-state>
<end-state id="AgentViewState" view="flowRedirect:contract" />
<view-state id="invalidCredentialsState"  view="logout" >
    <on-entry>
        <evaluate           
            expression="new com.iri.rpm.web.ui.beans.authentication.LoginCredential()"
            result="viewScope.loginCredential" />
        <set name="viewScope.isLoginError" value="true" />  
    </on-entry>
    <transition on="verifyCredentials" to="validateCredentials">
        <evaluate expression="authenticationService.challengeUser(loginCredential)" result="flowScope.auth" />
    </transition>   
</view-state>

服务层类别为

AuthenticationServiceImpl.java

package com.iri.rpm.web.ui.services;
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import com.iri.rpm.web.ui.beans.authentication.LoginCredential; 
public class AuthenticationServiceImpl implements IAutheticationService {
@Autowired
private AuthenticationManager authenticationManager; 
@Override
public LoginCredential challengeUser(LoginCredential loginCredential) {
    Authentication authentication = createPreAuthenticatedAuthenticationToken(loginCredential.getLoginUserId());
    try {
        if ((loginCredential.getPassword() == null) ||  (loginCredential.getPassword() == "")) {
            // default it to something else;
            loginCredential.setPassword("xxxxx");
        }
        authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginCredential.getLoginUserId(), loginCredential.getPassword()));
        //authentication.setAuthenticated(true);
        loginCredential.setAuthenticated(true);
        SecurityContextHolder.getContext().setAuthentication(authentication);
    } catch (BadCredentialsException bce) {
        bce.printStackTrace();
        loginCredential.setAuthenticated(false);
        handleBadCredentialsException(loginCredential.getLoginUserId());
    } catch (Exception e) {
        e.printStackTrace();
        loginCredential.setAuthenticated(false);
        handleSystemException(loginCredential.getLoginUserId());
    }
    return loginCredential;
}
/**
 * Handle system exception and re route the user to login page.
 * 
 * @param loginCredential
 */
private void handleSystemException(String loginCredential) {
    Authentication authentication = createPreAuthenticatedAuthenticationToken(loginCredential);
    authentication.setAuthenticated(false);
    SecurityContextHolder.getContext().setAuthentication(authentication);
}
/**
 * Handle bad credential and re route the user to login page.
 * 
 * @param loginCredential
 */
private void handleBadCredentialsException(String loginCredential) {
    Authentication authentication = createPreAuthenticatedAuthenticationToken(loginCredential);
    authentication.setAuthenticated(false);
    SecurityContextHolder.getContext().setAuthentication(authentication);
}
/**
 * Util method to create pre authentication token
 * 
 * @param loginCredential
 * @return
 */
private Authentication createPreAuthenticatedAuthenticationToken(
        String loginCredential) {
    return new PreAuthenticatedAuthenticationToken(loginCredential, "");
}
@Override
public void logoutAuth() {
    SecurityContextHolder.getContext().setAuthentication(null);
}
}

将bean定义为

LoginCredential.java

package com.iri.rpm.web.ui.beans.authentication;
import java.io.Serializable;
public class LoginCredential  implements Serializable{
private static final long serialVersionUID = 1L;
private String loginUserId;
transient private String password;
private boolean authenticated;
public LoginCredential(){
       super();
}
public boolean isAuthenticated() {
    return authenticated; 
}
public void setAuthenticated(boolean authenticated) {
    this.authenticated = authenticated;
}
public String getPassword() {
    return password;
}
public void setPassword(String password) {
    this.password = password;
}
public String getLoginUserId() {
    return loginUserId;
}
public void setLoginUserId(String loginUserId) {
    this.loginUserId = loginUserId;
}
}

弹簧配置为

application-Context security.xml

<security:http auto-config="true" use-expressions="true">
    <security:form-login login-page="/flow/login" default-target-url="/flow/login" authentication-failure-url="/flow/login?login_error=1" />
    <security:intercept-url pattern="/flow/login**" access="permitAll"/>
    <security:intercept-url pattern="/flow/javax.faces.resource/**" access="permitAll"/>    
    <security:intercept-url pattern="/**" access="isAuthenticated()" />

    <security:logout  logout-success-url="/logout.xhtml"  invalidate-session="true" />
    <security:intercept-url pattern="/secure" method="POST" access="hasRole('ROLE_SUPERVISOR')"/>
</security:http>

<security:authentication-manager erase-credentials="true" alias="authenticationManager">
    <security:authentication-provider ref="ldapActiveDirectoryAuthProvider"/>
</security:authentication-manager>  
<bean id="ldapActiveDirectoryAuthProvider" class="com.iri.rpm.web.security.RPMActiveDirectoryLdapAuthenticationProvider">
    <constructor-arg value="infores.com" />
    <constructor-arg value="ldap://170.118.24.149:389" />
    <property name="userDetailsContextMapper" ref="rpmUserDetailsContextMapper"/>
</bean>
<bean id="rpmUserDetailsContextMapper" class="com.iri.rpm.web.security.RPMUserDetailsContextMapper"/>

我所要说的是,它正在进行身份验证,并在身份验证完成时进入相应的流,当凭据失败时,它会抛出相同的loginPage.xhtml,其中没有错误消息。厌倦了尝试几种方法来解决,但没有给出预期的结果。任何帮助都是真诚的。

错误标签可以在sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message变量中找到,因此在您的日志页面中添加${sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message},就会显示错误消息。

最新更新