Я использую форму входа для небольшого проекта в Spring, но у меня есть небольшая проблема, заключающаяся в том, что каждый раз, когда я вхожу в систему с помощью формы входа, я получаю перенаправление ошибки.
Это мой SecurityConfiguration.java
package com.ffuentese;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
private DataSource dataSource;
@Value("${spring.queries.users-query}")
private String usersQuery;
@Value("${spring.queries.roles-query}")
private String rolesQuery;
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.
jdbcAuthentication()
.usersByUsernameQuery(usersQuery)
.authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource)
.passwordEncoder(bCryptPasswordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/registration").permitAll()
.antMatchers("/**").hasAuthority("ADMIN").anyRequest()
.authenticated().and().csrf().disable().formLogin()
.loginPage("/login").failureUrl("/login?error=true")
.defaultSuccessUrl("/home")
.usernameParameter("email")
.passwordParameter("password")
.and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/").and().exceptionHandling()
.accessDeniedPage("/access-denied");
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**");
}
}
Моя форма входа:
<form th:action = "@{/login}" method = "POST" class = "form-signin">
<h3 class = "form-signin-heading" th:text = "Welcome"></h3>
<br/>
<input type = "text" id = "email" name = "email" th:placeholder = "Email"
class = "form-control" /> <br/>
<input type = "password" th:placeholder = "Password"
id = "password" name = "password" class = "form-control" /> <br />
<div align = "center" th:if = "${param.error}">
<p style = "font-size: 20; color: #FF1C19;">Email or contraseña errónea, por favor intente nuevamente.</p>
</div>
<button class = "btn btn-lg btn-primary btn-block" name = "Submit" value = "Login" type = "Submit" th:text = "Login"></button>
</form>
Мой loginController.java
package com.ffuentese;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.ffuentese.User;
@Controller
public class LoginController {
@Autowired
private UserService userService;
@RequestMapping(value = {"/", "/login"}, method = RequestMethod.GET)
public ModelAndView login(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("login");
return modelAndView;
}
@RequestMapping(value = "/home", method = RequestMethod.GET)
public ModelAndView homeV(){
ModelAndView modelAndView = new ModelAndView();
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
modelAndView.setViewName("home");
return modelAndView;
}
@RequestMapping(value = "/registration", method = RequestMethod.GET)
public ModelAndView registration(){
ModelAndView modelAndView = new ModelAndView();
User user = new User();
modelAndView.addObject("user", user);
modelAndView.setViewName("registration");
return modelAndView;
}
@RequestMapping(value = "/registration", method = RequestMethod.POST)
public ModelAndView createNewUser(@Valid User user, BindingResult bindingResult) {
ModelAndView modelAndView = new ModelAndView();
User userExists = userService.findUserByEmail(user.getEmail());
if (userExists != null) {
bindingResult
.rejectValue("email", "error.user",
"There is already a user registered with the email provided");
}
if (bindingResult.hasErrors()) {
modelAndView.setViewName("registration");
} else {
userService.saveUser(user);
modelAndView.addObject("successMessage", "User has been registered successfully");
modelAndView.addObject("user", new User());
modelAndView.setViewName("registration");
}
return modelAndView;
}
@RequestMapping(value = "/admin/home", method = RequestMethod.GET)
public ModelAndView home(){
ModelAndView modelAndView = new ModelAndView();
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
User user = userService.findUserByEmail(auth.getName());
modelAndView.addObject("userName", "Welcome " + user.getName() + " " + user.getLastName() + " (" + user.getEmail() + ")");
modelAndView.addObject("adminMessage","Content Available Only for Users with Admin Role");
modelAndView.setViewName("admin/home");
return modelAndView;
}
}
Таким образом, вместо перехода от входа к / home он попадает в / error. Сама ошибка представляет собой такую строку кода:
{"timestamp":"2018-04-04T21:28:28.944+0000","status":999,"error":"None","message":"No message available"}
Форма действительно работает, потому что, если я перейду из / error и перейду на любой защищенный URL-адрес, они могут быть открыты.
Обновлено: исходный код взят из этого репозитория, и я адаптировал его к своему собственному проекту. https://github.com/gustavoponce7/SpringSecurityLoginTutorial также объяснил здесь
Обновлено: Еще один момент, который я считаю важным, заключается в том, что если я вхожу в систему, а затем снова вхожу в систему, форма, похоже, работает нормально, переводя пользователя из входа в / домой, как и ожидалось. Это странно.
Вы справились с этой проблемой?
Так в чем же выход?
Вот мое решение stackoverflow.com/questions/61029340/…




Может дело в том, нет RequestMapping с ошибкой Param. Возможное решение
@RequestMapping(value = {"/", "/login"}, method = RequestMethod.GET)
public ModelAndView login(@RequestParam(value = "error", required = false)){
ModelAndView modelAndView = new ModelAndView();
if (error != null) {
modelAndView.setViewName("error page");
} else modelAndView.setViewName("login");
return modelAndView;
}
Также может быть вызвано отсутствием всех следующих папок в вашем проекте "/static/**", "/js/**", "/css/**", "/img/**", "/json/**", удалите эту конфигурацию или добавьте все папки.
Просто чтобы вы знали, что в моем случае это больше связано с редактированием.
Спасибо! Оказывается, web.ignoring().antMatchers() вызовет эту странную ошибку, если вы укажете здесь отсутствующую папку ресурсов или нестатический путь. Проверить stackoverflow.com/a/41147185/1192702
Вы можете добавить параметр always-use-default-target в URL-адрес успеха.
.defaultSuccessUrl("/home",true)
Это означает, что в случае успешного входа вы всегда будете отправлены на /home.
Я думаю, что нежелательное поведение вызвано тем, что страница с ошибкой по какой-то причине помещена в очередь, а затем, когда вход в систему будет успешным, вы «вернетесь» к этому.
Это не идеальное решение, но если вы не хотите переходить на предыдущую страницу после входа в систему, оно поможет предотвратить описанное вами поведение.
Это все равно вызовет ошибку, но теперь пользователи ее не увидят из-за принудительного перенаправления.
Думаю, на вопрос дан ответ, сегодня я столкнулся с этой ошибкой, и у меня была другая ситуация. Я думал, что это поможет некоторым другим новым весенним кодерам, так как мне пришлось некоторое время гуглить.
Необходимо добавить имя атрибута в текстовые поля имени пользователя или пароля. После добавления атрибутов name = "username" и name = "password" в соответствующие типы ввода вы должны иметь возможность войти в систему.
Spring использует параметр name для сопоставления имени пользователя и пароля. так что это обязательно! это может показаться простым, но вот как это работает
создать контроллер и обработать запрос по умолчанию (т.е. получить '/'), если вы впервые используете аутентификацию по умолчанию
Ответ, который подходит и для моего случая, принадлежит 123.
Пригодился и следующий совет от https://www.baeldung.com/spring-security-login:
One reason to override most of the defaults in Spring Security is to hide the fact that the application is secured with Spring Security and minimize the information a potential attacker knows about the application.
Следующее в https://docs.spring.io/spring-security/site/docs/4.2.12.RELEASE/apidocs/org/springframework/security/config/annotation/web/configurers/AbstractAuthenticationFilterConfigurer.html также полезно ссылаться на:
defaultSuccessUrl(String defaultSuccessUrl) Specifies where users will go after authenticating successfully if they have not visited a secured page prior to authenticating.
defaultSuccessUrl(String defaultSuccessUrl, boolean alwaysUse) Specifies where users will go after authenticating successfully if they have not visited a secured page prior to authenticating or alwaysUse is true.
В моем случае это были некоторые другие запросы (один из них был 404 при загрузке ресурса css). После их исправления эта ошибка исчезла.
РЕДАКТИРОВАТЬ
Для правильного решения проблемы необходимо исключить страницу /error из весенних фильтров безопасности. Подробности смотрите в Spring безопасность перенаправляет на страницу с кодом состояния 999.
Вы нашли для этого решение?