为什么authentication-failure-url在spring security中不起作用

时间:2015-06-28 20:32:31

标签: spring spring-security

我在我的网站上使用spring security,但是当我使用自定义登录表单(JSF表单),并且用户输入了错误的凭据时,authentication-failure-url无效,用户也没有转发到{{ 1}},但failed.xhtml出现了

我不知道原因,请帮忙:

的applicationContext.xml:

index.xhtml

login.xhtml:

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">


    <context:component-scan base-package="com.myspring" />
    <context:annotation-config />

    <!-- beans configuration -->
    <beans:bean id="userBo" class="com.myspring.user.bo.impl.UserBoImpl" />



    <!-- security configuration -->
    <http auto-config="true">

        <intercept-url pattern="/login.xhtml" access="permitAll" />
        <intercept-url pattern="/index.xhtml" access="hasRole('ROLE_USER')" />
        <intercept-url pattern="/authenticated.xhtml" access="hasRole('ROLE_USER')" />
        <intercept-url pattern="/views/admin/**" access="hasRole('ROLE_USER')" />

        <form-login login-page="/login.xhtml" default-target-url="/authenticated.xhtml"
            authentication-failure-url="/failed.xhtml" />
        <logout invalidate-session="true" delete-cookies="true" logout-success-url="/"/>
        <csrf disabled="true" />
    </http>
    <authentication-manager alias="authenticationManager">
        <authentication-provider>
            <user-service>
                <user name="user1" password="user1Pass" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

</beans:beans>

这是带登录方法的loginController:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
</h:head>
<h:body>
    <div style="">
        <h:form id="loginFormId" prependId="false">
            <div id="loginFieldsPnlId">
                <div id="loginFieldUsrContId">
                    <h:outputText id="outTxtUserNameId" value="Username: "
                        name="outTxtUserNameNm"></h:outputText>
                    <h:inputText id="userName" required="true"
                        value="#{loginController.userName}"
                        requiredMessage="Please enter username"></h:inputText>
                    <h:outputLabel id="outLblUserNameId" for="userName"
                        name="outLblUserNameNm"></h:outputLabel>
                </div>
                <div id="loginFieldPassContId">
                    <h:outputText id="outTxtPasswordId" value="Password: "
                        name="outTxtPasswordNm"></h:outputText>
                    <h:inputSecret id="password" required="true"
                        value="#{loginController.password}"
                        requiredMessage="Please enter password" name="inTxtPasswordNm"></h:inputSecret>
                    <h:outputLabel id="outLblPasswordId" for="password"
                        name="outLblPasswordNm"></h:outputLabel>
                </div>
            </div>
            <div id="loginBtnPanelId">
                <h:commandButton id="btnLoginId" value="Login"
                    action="#{loginController.login}" styleClass="loginPanelBtn"></h:commandButton>
                <h:commandButton id="btnCancelId" value="Cancel"
                    action="#{loginController.cancel}" styleClass="loginPanelBtn"
                    immediate="true" update="loginFormId"></h:commandButton>
            </div>
        </h:form>
    </div>
    <div>
        <h:messages></h:messages>
    </div>
</h:body>
</html>

我也会添加项目结构:

enter image description here

1 个答案:

答案 0 :(得分:1)

由于您使用的是JSF,因此您基本上绕过了Spring Security提供的登录(和注销)功能。由于您的LoginControllersec:login-form几乎没用,因此sec:legato基本上已取而代之。

解决方案很简单,不要使用JSF,您仍然可以使用Facelets来呈现您的网页,但只需添加一个普通form标记,该标记会发布到/login而不是{{1}标签,您可以删除h:form

注意:如果你的应用程序根应用程序(即映射到LoginController),则需要在网址中加入/ 。因此,而不是/context-path使用/login

/context-path/login

如果您仍然想使用JSF而<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"> <h:head> </h:head> <h:body> <div style=""> <form id="loginFormId" method="post" action="/login"> <div id="loginFieldsPnlId"> <div id="loginFieldUsrContId"> <label>Username:<label> <input type="text" id="username" name="username" /> </div> <div id="loginFieldPassContId"> <label>Password:<label> <input type="password" id="password" name="password" /> </div> </div> <div id="loginBtnPanelId"> <button>Login</button> </div> </form> </div> </h:body> </html> ,请不要直接使用LoginController,而是将请求转发到AuthenticationManager网址,以便Spring Security接管在JSF完成所需的验证之后。