我正在尝试编写一个具有弹簧安全性的应用程序,用于在 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>
为此的流程是
登录.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定义为
登录凭据.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;
}
}
弹簧配置为
应用程序上下文安全.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 而没有错误消息。厌倦了尝试几种方法来解决没有给出预期结果的方法。真的很感激任何帮助。