I'm getting a null value even filling the field and passing the correct parameters, but something is not coming out right, look at this login page image filled in correctly https://uploaddeimagens.com.br/imagens/P6b20Tg
SpringSecurity
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity
public class SpringSecurity {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public static PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests((authorize)-> authorize
.antMatchers("/register/**").permitAll()
.antMatchers("/index").permitAll()
.antMatchers("/users").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
).formLogin(
form -> form
.loginPage("/login")
.loginProcessingUrl("/login")
.defaultSuccessUrl("/users")
.permitAll()
).logout(
logout -> logout
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.permitAll()
);
return http.build();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
}
AuthController
package com.xxxxxxxxxxxxxxxxxxxxxxxxxx.controller;
import com.xxxxxxxxxxxxxxxxxxxxxxxxxx.dto.UserDto;
import com.xxxxxxxxxxxxxxxxxxxxxxxxxx.entity.User;
import com.xxxxxxxxxxxxxxxxxxxxxxxxxx.service.UserService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import javax.validation.Valid;
import java.util.List;
@Controller
public class AuthController {
private UserService userService;
public AuthController(UserService userService) {
this.userService = userService;
}
@GetMapping("index")
public String home(){
return "index";
}
@GetMapping("/login")
public String loginForm() {
return "login";
}
// método handler para lidar com a solicitação de registro do usuário
@GetMapping("register")
public String showRegistrationForm(Model model){
UserDto user = new UserDto();
model.addAttribute("user", user);
return "register";
}
// método manipulador para lidar com a solicitação de envio do formulário de registro do usuário
@PostMapping("/register/save")
public String registration(@Valid @ModelAttribute("user") UserDto user,
BindingResult result,
Model model){
User existing = userService.findByEmail(user.getEmail());
if (existing != null) {
result.rejectValue("email", null, "Já existe uma conta cadastrada com esse e-mail");
}
if (result.hasErrors()) {
model.addAttribute("user", user);
return "register";
}
userService.saveUser(user);
return "redirect:/register?success";
}
@GetMapping("/users")
public String listRegisteredUsers(Model model){
List<UserDto> users = userService.findAllUsers();
model.addAttribute("users", users);
return "users";
}
}
UserDto
package com.xxxxxxxxxxxxxxxxxxxxxxxxxxxxx.dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class UserDto
{
private Long id;
@NotEmpty
private String Name;
@NotEmpty
private String CPF;
@NotEmpty(message = "O CPF não deve estar vazio")
@Email
private String email;
@NotEmpty(message = "A senha não deve estar vazia")
private String password;
}
Role
package com.xxxxxxxxxxxxxxxxxxxxxxx.entity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import java.util.List;
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name="roles")
public class Role
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable=false, unique=true)
private String name;
@ManyToMany(mappedBy="roles")
private List<User> users;
}
User
package com.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.entity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name="users")
public class User
{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "Nome" ,nullable=false)
private String name;
@Column(nullable = false)
private String CPF;
@Column(nullable=false, unique=true)
private String email;
@Column(nullable=false)
private String password;
@ManyToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL)
@JoinTable(
name="users_roles",
joinColumns={@JoinColumn(name="USER_ID", referencedColumnName="ID")},
inverseJoinColumns={@JoinColumn(name="ROLE_ID", referencedColumnName="ID")})
private List<Role> roles = new ArrayList<>();
}
RoleRepository
package com.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.repository;
import com.xxxxxxxxxxxxxxxxxxxxxxxxx.entity.Role;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RoleRepository extends JpaRepository<Role, Long> {
Role findByName(String name);
}
UserRepository
package com.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.repository;
import com.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmail(String email);
}
CustomUserDetailsService
package com.xxxxxxxxxxxxxxxxxxxxxxxxxxxx.service;
import com.xxxxxxxxxxxxxxxxxxxxxxxxxxxxx.entity.Role;
import com.xxxxxxxxxxxxxxxxxxxxxxxxxxxxx.entity.User;
import com.xxxxxxxxxxxxxxxxxxxxxxxxxxxxx.repository.UserRepository;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.stream.Collectors;
@Service
public class CustomUserDetailsService implements UserDetailsService {
private UserRepository userRepository;
public CustomUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userRepository.findByEmail(email);
if (user != null) {
return new org.springframework.security.core.userdetails.User(user.getEmail(),
user.getPassword(),
mapRolesToAuthorities(user.getRoles()));
}else{
throw new UsernameNotFoundException("Invalid username or password.");
}
}
private Collection < ? extends GrantedAuthority> mapRolesToAuthorities(Collection <Role> roles) {
Collection < ? extends GrantedAuthority> mapRoles = roles.stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
return mapRoles;
}
}
UserServiceImpl
package com.xxxxxxxxxxxxxxxxxxxxxxxxxx.service.impl;
import com.xxxxxxxxxxxxxxxxxxxxxxxxxx.dto.UserDto;
import com.xxxxxxxxxxxxxxxxxxxxxxxxxx.entity.Role;
import com.xxxxxxxxxxxxxxxxxxxxxxxxxx.entity.User;
import com.xxxxxxxxxxxxxxxxxxxxxxxxxx.repository.RoleRepository;
import com.xxxxxxxxxxxxxxxxxxxxxxxxxx.repository.UserRepository;
import com.xxxxxxxxxxxxxxxxxxxxxxxxxx.service.UserService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class UserServiceImpl implements UserService {
private UserRepository userRepository;
private RoleRepository roleRepository;
private PasswordEncoder passwordEncoder;
public UserServiceImpl(UserRepository userRepository,
RoleRepository roleRepository,
PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.roleRepository = roleRepository;
this.passwordEncoder = passwordEncoder;
}
@Override
public void saveUser(UserDto userDto) {
User user = new User();
user.setName(userDto.getName() + " " + userDto.getCPF());
user.setEmail(userDto.getEmail());
// criptografar a senha usando o spring security
user.setPassword(passwordEncoder.encode(userDto.getPassword()));
Role role = roleRepository.findByName("ROLE_ADMIN");
if(role == null){
role = checkRoleExist();
}
user.setRoles(Arrays.asList(role));
userRepository.save(user);
}
@Override
public User findUserByEmail(String email) {
return userRepository.findByEmail(email);
}
@Override
public User findByEmail(String email) {
return null;
}
@Override
public List<UserDto> findAllUsers() {
List<User> users = userRepository.findAll();
return users.stream()
.map((user) -> mapToUserDto(user))
.collect(Collectors.toList());
}
private UserDto mapToUserDto(User user){
UserDto userDto = new UserDto();
String[] str = user.getName().split(" ");
userDto.setName(str[0]);
userDto.setCPF(str[1]);
userDto.setEmail(user.getEmail());
return userDto;
}
private Role checkRoleExist(){
Role role = new Role();
role.setName("ROLE_ADMIN");
return roleRepository.save(role);
}
}
register.html
<!DOCTYPE html>
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
>
<head>
<meta charset="UTF-8">
<title>Registration and Login System</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" th:href="@{/index}">Registration and Login System</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" th:href="@{/login}">Login</a>
</li>
</ul>
</div>
</div>
</nav>
<br /><br /><br />
<div class="container">
<div class="row col-md-8 offset-md-2">
<div class="card">
<div class="card-header">
<h2 class="text-center">Registration</h2>
</div>
<div th:if="${param.success}">
<div class="alert alert-info">
You have successfully registered our app!
</div>
</div>
<div class="card-body">
<form
method="post"
role="form"
th:action="@{/register/save}"
th:object="${user}"
>
<div class="form-group mb-3">
<label class="form-label">First Name</label>
<input
class="form-control"
id="Name"
name="Name"
placeholder="Enter first name"
th:field="*{Name}"
type="text"
/>
<p th:errors = "*{Name}" class="text-danger"
th:if="${#fields.hasErrors('Name')}"></p>
</div>
<div class="form-group mb-3">
<label class="form-label">CPF</label>
<input
class="form-control"
id="CPF"
name="CPF"
placeholder="CPF"
th:field="*{CPF}"
type="text"
/>
<p th:errors = "*{CPF}" class="text-danger"
th:if="${#fields.hasErrors('CPF')}"></p>
</div>
<div class="form-group mb-3">
<label class="form-label">Email</label>
<input
class="form-control"
id="email"
name="email"
placeholder="Enter email address"
th:field="*{email}"
type="email"
/>
<p th:errors = "*{email}" class="text-danger"
th:if="${#fields.hasErrors('email')}"></p>
</div>
<div class="form-group mb-3">
<label class="form-label">Password</label>
<input
class="form-control"
id="password"
name="password"
placeholder="Enter password"
th:field="*{password}"
type="password"
/>
<p th:errors = "*{password}" class="text-danger"
th:if="${#fields.hasErrors('password')}"></p>
</div>
<div class="form-group">
<button class="btn btn-primary" type="submit">Register</button>
<span>Already registered? <a th:href="@{/login}">Login here</a></span>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
application.properties
spring.jpa.hibernate.ddl-auto=update
#logging.level.org.springframework=DEBUG
application.yml
spring:
datasource:
driver-class-name: org.firebirdsql.jdbc.FBDriver
url: jdbc:firebirdsql:localhost/3050:C:/DB/usuarios.FDB?sql_dialect=3&charSet=utf-8
username: SYSDBA
password: masterkey
hikari:
connection-timeout: 1000
login-timeout: 1000
minimum-idle: 10
jpa:
database-platform: org.hibernate.community.dialect.FirebirdDialect
hibernate:
ddl-auto: validate
spom.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.6.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.xxxxxxx</groupId>
<artifactId>xxxxxxxxxxx</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>DashBoardBackend</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
<squiggly.version>1.3.18</squiggly.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.firebirdsql.jdbc</groupId>
<artifactId>jaybird-jdk17</artifactId>
<version>3.0.10</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.5.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-community-dialects</artifactId>
<version>6.0.0.Alpha9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<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.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>com.github.bohnman</groupId>
<artifactId>squiggly-filter-jackson</artifactId>
<version>1.3.18</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Logback
2023-01-16 17:27:20.533 WARN 9548 --- [nio-8080-exec-8] o.a.c.util.SessionIdGeneratorBase : Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [154] milliseconds.
2023-01-16 17:27:38.328 WARN 9548 --- [nio-8080-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 335544347, SQLState: 23000
2023-01-16 17:27:38.328 ERROR 9548 --- [nio-8080-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : validation error for column "USERS"."CPF", value "*** null ***" [SQLState:23000, ISC error code:335544347]
2023-01-16 17:27:38.334 WARN 9548 --- [nio-8080-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Warning Code: 0, SQLState: null
2023-01-16 17:27:38.334 WARN 9548 --- [nio-8080-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : Connection.isValid does not support non-zero timeouts, timeout value 5 has been ignored
2023-01-16 17:27:38.336 ERROR 9548 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
org.firebirdsql.jdbc.FBSQLExceptionInfo: validation error for column "USERS"."CPF", value "*** null ***"