Я использую данные Spring, Spring mvc, Spring Core, Spring Security, Maven, Tomcat, mysql.
Я изучаю Spring Security и пытаюсь создать приложение (регистрация + вход).
Регистрация работает, но страница входа возвращает ошибку, даже когда я ввожу действительные данные.
Я не знаю, почему она не работает. Спасибо за помощь!
Мой код:
repository
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Query("from User where username=:username")
public User findByUserName(@Param("username")String username);
}
@Repository
public interface RoleRepository extends JpaRepository<Role, Long>{
@Query("from Role where name=:name")
public Role findByRoleName(@Param("name")String name);
}
entity:
package com.myapp.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table
public class Role {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column
private Long rid;
@Column
private String name;
public Role() {
}
public Role(Long rid, String name) {
super();
this.rid = rid;
this.name = name;
}
public Long getRid() {
return rid;
}
public void setRid(Long rid) {
this.rid = rid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Role [rid=" + rid + ", name=" + name + "]";
}
}
@Entity
@Table
public class User {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column
private Long uid;
@Column
private String username;
@Column
private String password;
@ManyToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
@JoinTable
(name="users_roles",
joinColumns=@JoinColumn(name="user_id", referencedColumnName="uid"),
inverseJoinColumns=@JoinColumn(name="role_id", referencedColumnName="rid"))
private Collection<Role>roles;
public User() {
}
public User(Long uid, String username, String password, Collection<Role> roles) {
super();
this.uid = uid;
this.username = username;
this.password = password;
this.roles = roles;
}
public Long getUid() {
return uid;
}
public void setUid(Long uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Collection<Role> getRoles() {
return roles;
}
public void setRoles(Collection<Role> roles) {
this.roles = roles;
}
@Override
public String toString() {
return "User [uid=" + uid + ", username=" + username + ", password=" + password + ", roles=" + roles + "]";
}
}
service:
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserRepository userRepo;
@Autowired
private RoleRepository roleRepo;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user =userRepo.findByUserName(username);
if(user==null)
{
System.out.println("USER WAS NOT FOUND");
throw new UsernameNotFoundException("Invalid username or password");
}
System.out.println("USER REPO RETURN: L: "+user.getUsername()+" P: "+user.getPassword());
System.out.println(user.getUsername()+ user.getPassword());
org.springframework.security.core.userdetails.User userDetails= new org.springframework.security.core.userdetails.User(user.getUsername(),
user.getPassword(),
user.getRoles().stream().map(r->new SimpleGrantedAuthority(r.getName())).collect(Collectors.toList()));
return userDetails;
}
@Override
@Transactional
public User findByUserName(String name) {
return userRepo.findByUserName(name);
}
@Override
@Transactional
public void save(User user)
{
User protectedUser=new User();
Set<Role>roles=new HashSet<>();
roles.add(roleRepo.findByRoleName("ROLE_EMPLOYEE"));
protectedUser.setUsername(user.getUsername());
protectedUser.setPassword(passwordEncoder.encode(user.getPassword())); protectedUser.setRoles(roles);
userRepo.save(protectedUser);
}
}
public interface UserService extends UserDetailsService{
public User findByUserName(String username);
public void save(User user);
}
Config:
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer{
}
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
private UserService userService;
@Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
/*
@Autowired
private CustomAuthenticationProvider ownProvider;
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").hasRole("EMPLOYEE")
.and()
.formLogin()
.loginPage("/showMyLoginPage")
.loginProcessingUrl("/authenticateTheUser")
.successHandler(customAuthenticationSuccessHandler)
.permitAll()
.and()
.logout().permitAll()
.and()
.exceptionHandling().accessDeniedPage("/denied-page");
}
@Bean
public BCryptPasswordEncoder passwordEncoder()
{
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
auth.setUserDetailsService(userService);
auth.setPasswordEncoder(passwordEncoder());
return auth;
}
}
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
@Override
protected Class<?>[] getRootConfigClasses() {
// TODO Auto-generated method stub
return new Class[] {};
}
@Override
protected Class<?>[] getServletConfigClasses() {
// TODO Auto-generated method stub
return new Class[] {WebMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
// TODO Auto-generated method stub
return new String[] {"/"};
}
}
@Configuration
@EnableWebMvc
@ComponentScan(basePackages= {"com.myapp"})
public class WebMvcConfig implements WebMvcConfigurer{
@Bean
public InternalResourceViewResolver viewResolver()
{
InternalResourceViewResolver viewResolver=new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
@Override
public Validator getValidator() {
LocalValidatorFactoryBean validator=new LocalValidatorFactoryBean();
return validator;
}
}
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider{
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String name=authentication.getName();
String password=authentication.getCredentials().toString();
System.out.println("CUSTOM AUTHENTICATION PROVIDER : NAME: "+name+" Password: "+password);
return null;
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Autowired
private UserService userService;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
System.out.println("\n\nIn customAuthenticationSuccessHandler\n\n");
String userName = authentication.getName();
System.out.println("userName=" + userName);
User theUser = userService.findByUserName(userName);
HttpSession session = request.getSession();
session.setAttribute("user", theUser);
response.sendRedirect(request.getContextPath() + "/");
}
}
controllers:
@Controller
public class LoginController {
@GetMapping("/showMyLoginPage")
public String showMyLoginPage()
{
return "login-page";
}
}
@Controller
public class MainController {
@GetMapping("/")
public String home()
{
return "home";
}
@GetMapping("/system")
public String system()
{
return "system";
}
}
@Controller
@RequestMapping("/register")
public class RegisterController {
@Autowired
private UserService userService;
@GetMapping("/showRegisterForm")
public String showRegisterForm(Model model)
{
User user=new User();
model.addAttribute(user);
return "register-form";
}
@PostMapping("/saveUser")
public String saveUser(@ModelAttribute("user") User user)
{
userService.save(user);
return "register-confirmation";
}
}
и jsp:
login:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1" isELIgnored="false"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form:form method="post" action="${pageContext.request.contextPath}/authenticateTheUser">
<c:if test="${param.error != null}">
<i style="color:red;">Sorry! You entered invalid date.</i>
</c:if>
<p>User name: <input type="text" name="username"/> </p>
<p>Password: <input type="password" name="password"/> </p>
<input type="submit" value="Login"/>
</form:form>
Register here! <a href="${pageContext.request.contextPath}/register/showRegisterForm" > Register now!</a>
</body>
</html>
register:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1" isELIgnored="false"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Registration form</title>
</head>
<body>
<form:form action="${pageContext.request.contextPath}/register/saveUser" modelAttribute="user">
Name: <form:input path="username"/>
Password <form:password path="password"/>
<button type="submit">Register</button>
</form:form>
</body>
</html>