2012-05-26 1 views
1

Я использую Spring (3.1), Spring MVC (3.1) и Spring Security (3.0) в комбинации, и я поставил вместе с одной страницей JSP, которая имеет две формы; Один - это форма для входа в систему, а другая - форма для регистрации (т. Е. Создание нового пользователя).Spring 3.1 MVC и безопасность: как логин, так и форма регистрации (несколько форм) на той же странице отправлены

Для формы регистра, я использую теги Spring form, подкрепленные контроллером для обработки запроса, но для формы входа я не беспокоюсь с тегами Spring form, поскольку я не считаю, что они нужны , Также нет контроллера, который мне нужно написать для обработки представления формы, поскольку Spring Security заботится об аутентификации, пока запрос отправлен в j_spring_security_check.

Форма регистра работает нормально, но форма входа в систему является проблемой. Кажется, что когда я нажимаю кнопку отправки в форме входа в систему, также регистрируется форма регистрации, или, по крайней мере, Весна думает, что я пытаюсь отправить эту форму. Вот 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) 

Это я признаю тех случаев, когда вы забываете включить атрибут modelAttribute в form:form, но, конечно, я не хочу передать эту форму моему контроллеру.

У меня такое чувство, что я ошибаюсь, я делаю или простое решение. Может кто-нибудь порекомендовать путь вокруг этого или, возможно, другого подхода?

Вот метод управления, который обрабатывает запросы на регистрацию в случае, если это необходимо:

@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

Если вы используете «user» modelAttribute в теге формы, тогда атрибут ненулевого запроса должен содержать с именем «пользователь».

Один из способов добавить, что в атрибуте запроса - это то, что вы сделали в своем ответе выше. Другие способы являются:

(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 method и Using @ModelAttribute on a method argument

Также обратите внимание, что вам не нужно использовать атрибут типа. См. form:input и form:password.

+0

Хорошие советы. Я приму это как правильный ответ. – chrisjleu

0

Я думаю, что проблема именно, когда Логин не удается, и та же страница подается вверх, хотя и на другой URL пути и так через другой метод контроллера. Поэтому мое первоначальное подозрение, что проблема в том, что обе формы представлены, может быть чем-то вроде красной селедки, хотя я до сих пор не совсем понимаю, что происходит, и это может все же иметь к этому какое-то отношение. В любом случае, это то, что исправила проблему для меня:

У меня был метод контроллера, который изначально выглядел следующим образом:

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

В контексте Spring Security я указать /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 на аргумент метода указывает, что аргумент должен быть извлечен из модели. Если в модели нет, аргумент должен быть сначала создан, а затем добавлен в модель. " Поскольку вы не привязываете параметры запроса, ваше решение эквивалентно добавлению нового объекта User в модель. Кроме того, BindingResult не нужен в подписи. – Ritesh