6

我创建了一个简单的 JSF 登录页面,并尝试将它与 Spring Security 集成。

这是login.xhtml中的表单元素

    <h:form>

     <h:outputLabel value="User Id:" for="userId"/>

     <h:inputText id="j_username" label="User Id"
     required="true"   value="#{loginBean.name}" >

     </h:inputText>

     <h:outputLabel value="Password: "  for ="password"/>

     <h:inputSecret id="j_password" value="#{loginBean.password}" />

     <h:commandButton value="Submit" action="#{j_spring_security_check}" />

 </h:form>

但是呈现的 html 页面有如下内容。查看表单操作和输入标签的名称

表单元素

  <form id="j_idt6" name="j_idt6" method="post" 
    action="/jsfproject2/faces/login.xhtml"
       enctype="application/x-www-form-urlencoded">

和输入标签

   User Id:</label><input id="j_idt6:j_username" type="text"
     name="j_idt6:j_username" />

现在我希望表单动作/j_spring_security_check和输入框是'j_username'和j_password

我们怎样才能做到这一点?

4

2 回答 2

14

Spring Security 有两种工作方式。

prependId="false"在 JSF 表单上使用

作为<h:form>一个命名容器,它会在其子项的 id 之前添加指定id的 id 或自动生成的 id,因此 Spring Security 期望 id 保持未链接,只是不要在 id 之前添加:

 <h:form prependId="false">
     <h:outputLabel value="User Id: " for="userId" />
     <h:inputText id="j_username" label="User Id" required="true" value="#{loginBean.name}" />
     <h:outputLabel value="Password: "  for ="password" />
     <h:inputSecret id="j_password" value="#{loginBean.password}" />
     <h:commandButton value="Submit" action="#{loginBean.login}" />
</h:form>

注意这#{j_spring_security_check}是错误的动作方法:它需要#{loginBean.login}具有以下内容:

public String login() {
    //do any job with the associated values that you've got from the user, like persisting attempted login, etc.
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext extenalContext = facesContext.getExternalContext();
    RequestDispatcher dispatcher = ((ServletRequest)extenalContext.getRequest()).getRequestDispatcher("/j_spring_security_check");
    dispatcher.forward((ServletRequest)extenalContext.getRequest(), (ServletResponse)extenalContext.getResponse());
    facesContext.responseComplete();
    return null;
}

基本上,您需要做的就是发送到/j_spring_security_check并拥有j_usernamej_password作为请求参数。

使用纯 HTML 表单

基本上,在这个问题上没有特别需要弄乱 JSF 表单,以防您除了身份验证之外不需要做一些额外的事情,而纯 HTML 表单足以让 Spring Security 完成它的工作。

<form action="/j_spring_security_check" method="POST">
    <label for="j_username">User Id: </label>
    <input id="j_username" name="j_username" type="text" />
    <label for="j_password">Password: </label>
    <input id="j_password" name="j_password" type="password"/>
    <input type="submit" value="Submit"/>
</form>
于 2013-05-24T11:11:59.090 回答
1

我就是这样做的:

<form action="${request.contextPath}/appLogin" method="POST">
     <h:form prependId="false">
         <p:inputText id="app_username" placeholder="Username" name="app_username" styleClass="Wid80 TexAlCenter Fs18" required="true"/>
         <p:password id="app_password" placeholder="Password" name="app_password"  label="Password" required="true" styleClass="Wid80 TexAlCenter Fs18"/>
         <button type="submit" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only Wid60">
            <span class="ui-button-text">Login</span>
         </button>      
     <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>    
     </h:form>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form> 

我正在使用 Primefaces 的高级主题 Ronin 和自定义登录 URL,如“appLogin”和自定义参数,如“app_username”。

于 2016-10-23T09:17:33.480 回答