2012-05-26 44 views
1

我使用Spring(3.1),Spring MVC(3.1)和Spring Security(3.0)在一起的一個JSP頁面上有兩種形式;一種是登錄表單,另一種是註冊表單(即創建新用戶)。Spring 3.1 MVC和安全:同一頁面上的登錄和註冊表單(多個表單)獲取提交

對於註冊表格,我使用Spring form標籤,由控制器備份以處理請求,但對於登錄表單,我不打擾Spring form標籤,因爲我不相信它們是必需的。也沒有控制器需要編寫來處理表單提交,因爲只要請求被提交到j_spring_security_check,Spring Security負責驗證。

註冊表格工作正常,但登錄表單是一個問題。似乎當我點擊登錄表單上的提交按鈕時,註冊表單也被提交,或者至少Spring認爲我正在嘗試提交該表單。下面是JSP:

<form id="loginform" method="POST" action="<c:url value='j_spring_security_check'/>"> 
     <label for="existing_email">Email:</label> 
     <input name="j_username" id="existing_email" type="text" value="${SPRING_SECURITY_LAST_USERNAME}" /> 

     <label for="existing_password">Password:</label> 
     <input name="j_password" id="existing_password" type="password" /> 

     <input id="login-form-submit" type="submit" value="Sign in" /> 
    </form> 

    <form:form id="registrationform" modelAttribute="user" method="POST" action="register"> 
     <form:label path="username" for="email">Email:</form:label> 
     <form:input path="username" name="username" id="email" type="text" /> 
     <form:errors path="username" cssClass="formError" /> 

     <form:label path="password" for="password">Password:</form:label> 
     <form:input path="password" name="password" id="password" type="password" /> 
     <form:errors path="password" cssClass="formError" /> 

     <input id="registration-form-submit" type="submit" value="Sign up" /> 
    </form:form> 

注意form標籤類型的輸入提交不存在,這似乎是我見過的例子做一個正常的事情。將表單標籤添加到提交按鈕我猜測沒有意義,因爲它沒有映射到目標對象上的任何內容(在這種情況下爲用戶)。

當我點擊「登錄」按鈕,我得到以下異常:

SEVERE: Servlet.service() for servlet [appServlet] in context with path [/project1] threw exception [An exception occurred processing JSP page /WEB-INF/views/registration.jsp at line 29 
28:   <form:form id="registrationform" modelAttribute="user" method="POST" action="register"> 
29:    <form:label path="username" for="username">Username:</form:label> 
30:    <form:input path="username" name="username" id="username" type="text" /> 
31:    <form:errors path="username" cssClass="formError" /> 
32:    


Stacktrace:] with root cause 
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'user' available as request attribute 
    at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:141) 

這是我從那裏你忘了,包括在form:form中的ModelAttribute屬性的情況下承認,但我當然不希望將此表格提交給我的控制器。

我有一種感覺,我正在犯一個錯誤或一個簡單的解決方案。任何人都可以推薦一個解決這個問題的方法或者一個不同的方法?

這裏是控制器方法處理請求的情況下,以註冊真實需要:

@RequestMapping(value = "**/register", method = RequestMethod.POST) 
    public String registerUser(@ModelAttribute("user") @Validated User user, BindingResult errors, ModelMap model) { 
     if (errors.hasErrors()) { 
      return "registration"; 
     } 
     // Other stuff then... 
     return "profile" 
    } 
+0

您在成功/失敗登錄後重定向用戶的位置? – Ritesh

+0

成功的登錄提供了不同的jsp頁面,但失敗的登錄提供了相同的頁面,即registration.jsp。 – chrisjleu

+0

其實Ritesh,這給了我一個線索,似乎問題是當登錄失敗,我重定向到相同的JSP,雖然通過不同的控制器方法。我會自己添加一個答案。 – chrisjleu

回答

1

如果您在表單標籤中使用「用戶」modelAttribute,則非空請求屬性必須與名稱「user」一起出現。

在請求屬性中添加的一種方法是您在上面的答案中所做的。其他的方法有:

(1)添加在ModelMap:

@RequestMapping(value = "/loginfailed", method = RequestMethod.GET) 
public String loginFailed(ModelMap model) { 
    model.addAttribute("user", new User()); 
    model.addAttribute("error", "true"); 
    return "registration"; 
} 

(2)添加在請求範圍(使用的WebRequest或HttpServletRequest的):

@RequestMapping(value = "/loginfailed", method = RequestMethod.GET) 
public String loginFailed(ModelMap model, WebRequest webRequest) { 
    webRequest.setAttribute("user", new User(), WebRequest.SCOPE_REQUEST); 
    model.addAttribute("error", "true"); 
    return "registration"; 
} 

(3)使用@ModelAttribute上方法:

@ModelAttribute("user") 
public User user() { 
    return new User(); 
} 

另請參閱Using @ModelAttribute on a methodUsing @ModelAttribute on a method argument

另請注意,您不必使用type屬性。見form:inputform:password

+0

好的提示謝謝。我會接受這是正確的答案。 – chrisjleu

0

我認爲這個問題是特別是當一個登錄失敗,同一頁面提供了,儘管是不同的URL路徑所以通過不同的控制器方法。因此,我最初懷疑問題是兩種表格都被提交可能是一個紅色的鯡魚,儘管我仍然不完全理解正在發生的事情,這可能與它有關。在任何情況下,這是糾正我的問題:

我最初看起來像這樣的控制方法:

@RequestMapping(value = "/loginfailed", method = RequestMethod.GET) 
public String loginFailed(ModelMap model) { 
    model.addAttribute("error", "true"); 
    return "registration"; 
} 

在春季安全方面,我指定/loginfailed因爲去的路徑如果登錄嘗試失敗,則爲默認。這是它似乎需要用戶對象,所以如果我改變了簽名如下所有的工作:

@RequestMapping(value = "/loginfailed", method = RequestMethod.GET) 
public String loginFailed(@ModelAttribute("user") User user, BindingResult errors, ModelMap model) { 
    model.addAttribute("error", "true"); 
    return "registration"; 
} 

任何其他人的意見/澄清歡迎。

+0

正如http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-modelattrib-method-args中提到的,「一個@ModelAttribute在方法參數指示參數應該從模型中檢索,如果模型中不存在,參數應該先實例化,然後添加到模型中。「由於您沒有綁定請求參數,因此您的解決方案等同於在模型中添加新的用戶對象。另外,簽名中不需要BindingResult。 – Ritesh

相關問題