Я новичок в Spring, но чтобы продолжить обучение, я работаю над Spring MVC App, но застрял с ошибкой.Я начал с демонстрационного проекта с курса Spring, который я сделал, и у него есть функции входа в систему, выхода из системы и регистрации, именно то, что я хочу сейчас.Что мне не понравилось в этом проекте, так это то, что от пользователя требуется указать имя пользователя и адрес электронной почты для создания новой учетной записи.Поэтому я изменил базовую таблицу базы данных, чтобы у нее было только имя пользователя (которая будет содержать адрес электронной почты), и я избавился от столбца электронной почты.Затем я в основном удалил каждую запись в коде.Все поля электронной почты, все получатели / установщики электронной почты, я удалил его из конструкторов, удалил каждую запись электронной почты на страницах jsp и прошел все контроллеры, нет ничего, что требовало бы свойства электронной почты.Но все же, если я запускаю приложение и нажимаю Зарегистрировать нового пользователя, я получаю:
org.springframework.beans.NotReadablePropertyException: Invalid property 'email' of bean class [com.luv2code.springsecurity.demo.user.CrmUser]: Bean property 'email' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
Аналогично, если я пытаюсь войти в систему сейчас, я получаю:
javax.el.PropertyNotFoundException: Property [email] not found on type [com.luv2code.springsecurity.demo.entity.User]
Сейчас,Я мог бы просто сказать, хорошо, забудь об этом, я продолжаю с именем пользователя и электронной почтой, но я хочу понять, что здесь происходит, прежде чем продолжить.Как получилось, например, поиск свойства электронной почты в CrmUser?То же самое относится и к классу сущностей User, поле электронной почты не осталось, так откуда это все-таки?Что я здесь упустил?Мое единственное оставленное предположение состоит в том, что интерфейсам, используемым в конфигурации безопасности для аутентификации, требуется поле электронной почты, но на данный момент я просто должен допустить это.Кто-нибудь может указать мне правильное направление, что я здесь не понимаю?СПАСИБО заранее, дайте мне знать, если потребуется больше кода или даже всего проекта.
Вот моя структура проекта:
Класс пользователя:
Класс CrmUser:
@FieldMatch.List({
@FieldMatch(first = "password", second = "matchingPassword", message = "The password fields must match")
})
public class CrmUser {
//@ValidEmail
@NotNull(message = "is required")
@Size(min = 1, message = "is required")
private String userName;
@NotNull(message = "is required")
@Size(min = 1, message = "is required")
private String password;
@NotNull(message = "is required")
@Size(min = 1, message = "is required")
private String matchingPassword;
@NotNull(message = "is required")
@Size(min = 1, message = "is required")
private String firstName;
@NotNull(message = "is required")
@Size(min = 1, message = "is required")
private String lastName;
// @ValidEmail
// @NotNull(message = "is required")
// @Size(min = 1, message = "is required")
// private String email;
public CrmUser() {
}
// getters/setters omitted for brevity
Контроллер регистрации:
@Controller
@RequestMapping("/register")
public class RegistrationController {
@Autowired
private UserService userService;
private Logger logger = Logger.getLogger(getClass().getName());
@InitBinder
public void initBinder(WebDataBinder dataBinder) {
StringTrimmerEditor stringTrimmerEditor = new StringTrimmerEditor(true);
dataBinder.registerCustomEditor(String.class, stringTrimmerEditor);
}
@GetMapping("/showRegistrationForm")
public String showMyLoginPage(Model theModel) {
theModel.addAttribute("crmUser", new CrmUser());
return "registration-form";
}
@PostMapping("/processRegistrationForm")
public String processRegistrationForm(@Valid @ModelAttribute("crmUser") CrmUser theCrmUser, BindingResult theBindingResult, Model theModel) {
String userName = theCrmUser.getUserName();
logger.info("Processing registration form for: " + userName);
// form validation
if (theBindingResult.hasErrors()){
return "registration-form";
}
// check the database if user already exists
User existing = userService.findByUserName(userName);
if (existing != null){
theModel.addAttribute("crmUser", new CrmUser());
theModel.addAttribute("registrationError", "User name already exists.");
logger.warning("User name already exists.");
return "registration-form";
}
// create user account
userService.save(theCrmUser);
logger.info("Successfully created user: " + userName);
return "registration-confirmation";
}
}
DemoSecurityConfig:
@Configuration
@EnableWebSecurity
public class DemoSecurityConfig extends WebSecurityConfigurerAdapter {
// add a reference to our security data source
@Autowired
private UserService userService;
@Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.antMatchers("/").hasRole("EMPLOYEE")
.antMatchers("/leaders/**").hasRole("MANAGER")
.antMatchers("/systems/**").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/showMyLoginPage")
.loginProcessingUrl("/authenticateTheUser")
.successHandler(customAuthenticationSuccessHandler)
.permitAll()
.and()
.logout().permitAll()
.and()
.exceptionHandling().accessDeniedPage("/access-denied");
}
//beans
//bcrypt bean definition
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
//authenticationProvider bean definition
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
auth.setUserDetailsService(userService); //set the custom user details service
auth.setPasswordEncoder(passwordEncoder()); //set the password encoder - bcrypt
return auth;
}
}
UserDaoImpl:
@Repository
public class UserDaoImpl implements UserDao {
// need to inject the session factory
@Autowired
private SessionFactory sessionFactory;
@Override
public User findByUserName(String theUserName) {
// get the current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
// now retrieve/read from database using username
Query<User> theQuery = currentSession.createQuery("from User where userName=:uName", User.class);
theQuery.setParameter("uName", theUserName);
User theUser = null;
try {
theUser = theQuery.getSingleResult();
} catch (Exception e) {
theUser = null;
}
return theUser;
}
@Override
public void save(User theUser) {
// get current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
// create the user ... finally LOL
currentSession.saveOrUpdate(theUser);
}
}
UserServiveImpl:
@Service
public class UserServiceImpl implements UserService {
// need to inject user dao
@Autowired
private UserDao userDao;
@Autowired
private RoleDao roleDao;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@Override
@Transactional
public User findByUserName(String userName) {
// check the database if the user already exists
return userDao.findByUserName(userName);
}
@Override
@Transactional
public void save(CrmUser crmUser) {
User user = new User();
// assign user details to the user object
user.setUserName(crmUser.getUserName());
user.setPassword(passwordEncoder.encode(crmUser.getPassword()));
user.setFirstName(crmUser.getFirstName());
user.setLastName(crmUser.getLastName());
//user.setEmail(crmUser.getEmail());
// give user default role of "employee"
user.setRoles(Arrays.asList(roleDao.findRoleByName("ROLE_EMPLOYEE")));
// save user in the database
userDao.save(user);
}
@Override
@Transactional
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
User user = userDao.findByUserName(userName);
if (user == null) {
throw new UsernameNotFoundException("Invalid username or password.");
}
return new org.springframework.security.core.userdetails.User(user.getUserName(), user.getPassword(),
mapRolesToAuthorities(user.getRoles()));
}
private Collection<? extends GrantedAuthority> mapRolesToAuthorities(Collection<Role> roles) {
return roles.stream().map(role -> new SimpleGrantedAuthority(role.getName())).collect(Collectors.toList());
}
}
registration-form.jsp:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="Vogt Pferdedeckenreinigung">
<meta name="author" content="MB">
<title>Pferdedeckenwäscherei und Reparaturservice Vogt - Registrierung</title>
<!-- Get local CSS files -->
<spring:url value="/resources/css/styles.css" var="mainCss" />
<spring:url value="/resources/css/bootstrap.min.css" var="bootstrapCss" />
<!-- Get local JS files -->
<spring:url value="/resources/js/bootstrap.min.js.download" var="bootstrapJS" />
<spring:url value="/resources/js/jquery-3.3.1.slim.min.js.download" var="jqueryJS" />
<spring:url value="/resources/js/popper.min.js.download" var="popperJS" />
<link href="${mainCss}" rel="stylesheet" />
<link href="${bootstrapCss}" rel="stylesheet" />
<script src="${bootstrapJS}"></script>
<script src="${jqueryJs}"></script>
<script src="${popperJS}"></script>
</head>
<body class="text-center">
<div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column">
<header class="masthead mb-auto">
<div class="inner">
<h3 class="masthead-brand">Vogt</h3>
<nav class="nav nav-masthead justify-content-center">
<a class="nav-link" href="${pageContext.request.contextPath}/.">Bestellung</a>
<a class="nav-link active" href="${pageContext.request.contextPath}/register/showRegistrationForm">Neukunde</a>
<a class="nav-link" href="https://www.pferdedeckenwaescherei-vogt.de/kontakt">Kontakt</a>
</nav>
</div>
</header>
<main role="main" class="inner cover">
<body class="text-center">
<form:form action="${pageContext.request.contextPath}/register/processRegistrationForm"
modelAttribute="crmUser" class="form-signin">
<img class="mb-4" src="<spring:url value="/resources/img/logo.png"/>" alt="" width="559" height="152">
<h1 class="h3 mb-3 font-weight-normal">Registrieren</h1>
<div class="form-group">
<div class="col-xs-15">
<div>
<!-- Place for messages: error, alert etc ... -->
<div class="form-group">
<div class="col-xs-15">
<div>
<!-- Check for registration error -->
<c:if test="${registrationError != null}">
<div class="alert alert-danger col-xs-offset-1 col-xs-10">
${registrationError}
</div>
</c:if>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- User name -->
<form:errors path="userName" class="error" />
<form:input path="userName" placeholder="Username" class="form-control"/>
<!-- Password -->
<form:errors path="password" class="error" />
<form:password path="password" placeholder="password (*)" class="form-control" />
<!-- Confirm Password -->
<form:errors path="matchingPassword" class="error" />
<form:password path="matchingPassword" placeholder="confirm password (*)" class="form-control" />
<!-- First name -->
<form:errors path="firstName" class="error" />
<form:input path="firstName" placeholder="first name (*)" class="form-control" />
<!-- Last name -->
<form:errors path="lastName" class="error" />
<form:input path="lastName" placeholder="last name (*)" class="form-control" />
<!-- Email
<form:errors path="email" class="error" />
<form:input path="email" placeholder="email (*)" class="form-control" />
-->
<!-- Login/Submit Button -->
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> Anmeldedaten speichern
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Registrieren</button>
</form:form>
</main>
</div>
</body>
</html>