pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.snippets</groupId>
<artifactId>SpringSnippets</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringSnippets</name>
<description>Sample snippets for using in a project</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<!-- spring-security-config -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@Controller
public class ViewController {
@Autowired UserService userService;
@GetMapping("/user/login")
public String showLogin() {
return "login.html";
}
@GetMapping("/")
public String home() {
return "home.html";
}
@GetMapping(value = "/loginFailed")
public String loginError(Model model) {
model.addAttribute("error", "true");
return "login";
}
@GetMapping(value = "/logout")
public String logout(SessionStatus session) {
SecurityContextHolder.getContext().setAuthentication(null);
session.setComplete();
return "redirect:/welcome";
}
@GetMapping("/registration")
public String showRegistrationForm(Model model) {
UserDto userDto = new UserDto();
model.addAttribute("user", userDto);
return "register.html";
}
@PostMapping(value = "/postLogin")
public String postLogin(Model model, HttpSession session) {
// read principal out of security context and set it to session
UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
validatePrinciple(authentication.getPrincipal());
User loggedInUser = ((PdfUserDetails) authentication.getPrincipal()).getUserDetails();
model.addAttribute("currentUser", loggedInUser.getUserName());
session.setAttribute("userId", loggedInUser.getId());
return "register.html";
}
private void validatePrinciple(Object principal) {
if (!(principal instanceof PdfUserDetails)) {
throw new IllegalArgumentException("Principal can not be null!");
}
}
@PostMapping("/registration/confirm")
public String registerUserAccount( UserDto user) {
ModelAndView mav = new ModelAndView();
try {
userService.registerNewUserAccount(user);
} catch (UserExistsException uaeEx) {
mav.addObject("message", "An account for that username/email already exists.");
}
return "login.html";
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired UserDetailsService userDetailsService;
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Bean
public UserDetailsService userDetailsService() {
return new UserLoginService();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/css/**", "/js/**", "/images/**").permitAll()
.antMatchers("/registration").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/user/login")
.defaultSuccessUrl("/", true).permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/user/login")
.permitAll();
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
@Service
@Transactional
public class UserLoginService implements UserDetailsService {
@Autowired
UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
Optional<User> user = userRepository.findByUserName(userName);
if (user == null)
throw new UsernameNotFoundException("No user found with username: " + userName);
return new PdfUserDetails(user.get());
}
}
public class PdfUserDetails implements UserDetails {
private static final long serialVersionUID = 1L;
private User user;
public PdfUserDetails(User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> l1 = new ArrayList<GrantedAuthority>();
l1.add(new SimpleGrantedAuthority(this.user.getRole()));
return l1;
}
public Long getId() {
return user.getId();
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUserName();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public User getUserDetails() {
return user;
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
crossorigin="anonymous"></script>
<link rel="stylesheet" th:href="@{/css/login.css}">
</head>
<body>
<div class="container">
<div class="row justify-content-center">
<div class="col-4">
<form class="form-group" action="/postLogin" th:object="${user}" method="POST" enctype="utf8">
<h5 class="text-center text-info mb-2"> <label for="">Login</label></h5>
<div class="input-group my-2">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-user"></i></span>
</div>
<input name="username" type="text" class="form-control" placeholder="Username">
</div>
<div class="input-group my-2">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-unlock"></i></span>
</div>
<input name="password" type="password" class="form-control" placeholder="Password">
</div>
<button class="btn btn-outline-danger my-2 mx-5">Cancel</button>
<button class="btn btn-outline-success my-2 mx-2">Login</button>
<h6 class="text-center mt-3"><label for="">Not a member? <a th:href="@{/registration}">Signup</a></label></h6>
</form>
</div>
</div>
</div>
</body>
</html>
Я получаю сообщение об ошибке статуса 302 при попытке входа в систему с помощью настраиваемой формы, пожалуйста, помогите в решении проблемы. Я везде проверял и не могу понять, что не так. Я пытаюсь использовать безопасность Spring с помощью UserDetailsService, используя mysql db. В весенних документах процедура также не очень четко прописана, и я не могу решить проблему.