Not sure what is happening here. The error is
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'authenticationController': Unsatisfied dependency expressed through field 'userService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService' - Unsatisfied dependency expressed through constructor parameter 1"
Am I missing something here?
My controller -
import com.***.model.User;
import com.***.service.AuthTokenService;
import com.***.service.Authentication;
import com.***.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
#Controller
#RestController
#RequestMapping("/api/v1")
public class AuthenticationController {
#Autowired
UserService userService;
AuthTokenService authTokenService;
#GetMapping(path = "/users")
public ResponseEntity<?> listUser() {
List<User> resource = userService.getUser();
return ResponseEntity.ok(resource);
}
#PostMapping(path = "/register")
public ResponseEntity<?> register(#RequestBody User newUser) {
User user = userService.findUserByEmail(newUser.getEmail());
User unconfirmedUser = userService.registerUser(newUser);
return ResponseEntity.ok(unconfirmedUser);
}
My UserService -
import com.***.model.User;
import com.***.repository.UserRepository;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
#Component
#AllArgsConstructor
public class UserService {
#Autowired
UserRepository userRepository;
AuthTokenService authTokenService;
EmailSenderService emailSenderService;
void sendAuthenticationEmail(String userMail, String token) {
final SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setTo(userMail);
mailMessage.setSubject("Mail Confirmation Link!");
mailMessage.setFrom("<Mail Service>");
mailMessage.setText( "Thank you for joining ***! Please click below to activate your account." + "http://8080/api/v1/confirm?token=" + token);
emailSenderService.sendEmail(mailMessage);
}
public User registerUser(User user) {
final Authentication authenticationToken = new Authentication(user);
authTokenService.saveAuthenticationToken(authenticationToken);
sendAuthenticationEmail(user.getEmail(), authenticationToken.getUserToken());
return userRepository.save(user);
}
public void confirmUser(Authentication authenticationToken) {
final User user = authenticationToken.getUser();
user.setEnabled(true);
userRepository.save(user);
authTokenService.deleteAuthenticationToken((long) authenticationToken.getId());
}
}
Authentication -
import com.***.model.User;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import java.time.LocalDate;
import java.util.UUID;
#Entity
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class Authentication {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String userToken;
private LocalDate dateTimeCreated;
#OneToOne(targetEntity = User.class, fetch = FetchType.EAGER)
#JoinColumn(nullable = false, name = "id")
private User user;
Authentication(User user) {
this.user = user;
this.dateTimeCreated = LocalDate.now();
this.userToken = UUID.randomUUID().toString();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserToken() {
return userToken;
}
public void setUserToken(String userToken) {
this.userToken = userToken;
}
public LocalDate getDateTimeCreated() {
return dateTimeCreated;
}
public void setDateTimeCreated(LocalDate dateTimeCreated) {
this.dateTimeCreated = dateTimeCreated;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
Authentication token repo -
package com.***.repository;
import com.***.service.Authentication;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
#Repository
public interface AuthenticationTokenRepository extends CrudRepository<Authentication, Long> {
Optional<Authentication> findAuthenticationToken(String token);
}
Picture of file structure HERE
Log of error
Based on your error it looks like you don't know how to create JpqRepository method signature based queries. You can read about it here : https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods
I'm guessing that your method in AuthenticationTokenRepository called findAuthenticationToken(String someField) should be named findBySomeField(String someField). Also make sure you have getter for someField
Would be easier if you could provide your AuthenticationTokenRepository and Authenctication classes
Edit:
Change your method in AuthenticationTokenRepository to findByUserToken(String userToken)
Related
I am facing this exception in my project. I tried to connect my project with mongodb atlas, can any one please help me resolve this issue. Written the atlas configuration in application.properties file = spring.data.mongodb.uri = url with updated password.
Exception
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'authorServiceImpl': Unsatisfied dependency expressed through field 'authorRepository': Error creating bean with name 'authorRepository' defined in com.bookdekho.application.repository.AuthorRepository defined in #EnableMongoRepositories declared on MongoRepositoriesRegistrar.EnableMongoRepositoriesConfiguration: Cannot resolve reference to bean 'mongoTemplate' while setting bean property 'mongoOperations'
Author model
package com.bookdekho.application.model;
import com.bookdekho.application.enums.Genre;
import com.bookdekho.application.enums.UserType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import java.util.Set;
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Author {
#Id
private String id;
private UserType userType;
private Set<Genre> preferences;
private OnlineLinks onlineLinks;
private Set<String> authorImages;
private String primaryImageUrl;
private Set<String> aboutBooks;
private Set<String> bookReviewed;
private Long achievedPoints;
}
Author Repository
package com.bookdekho.application.repository;
import com.bookdekho.application.model.Author;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface AuthorRepository extends MongoRepository<Author, String> {
}
Author Service
package com.bookdekho.application.service;
import com.bookdekho.application.dto.AuthorDTO;
import com.bookdekho.application.model.Author;
import org.springframework.data.domain.Page;
public interface AuthorService {
AuthorDTO addAuthor(AuthorDTO authorDTO);
AuthorDTO updateAuthor(String userId, AuthorDTO authorDTO);
AuthorDTO getAuthorById(String authorId);
Page<Author> getAllAuthors(int page, int size);
void deleteAuthorById(String authorId);
}
Author Service Impl
package com.bookdekho.application.serviceimpl;
import com.bookdekho.application.dto.AuthorDTO;
import com.bookdekho.application.exception.EntityNotFoundException;
import com.bookdekho.application.model.Author;
import com.bookdekho.application.repository.AuthorRepository;
import com.bookdekho.application.service.AuthorService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
#Service
public class AuthorServiceImpl implements AuthorService {
#Autowired
private AuthorRepository authorRepository;
#Override
public AuthorDTO addAuthor(AuthorDTO authorDTO) {
Author author = new Author();
BeanUtils.copyProperties(authorDTO,author);
authorRepository.save(author);
BeanUtils.copyProperties(author,authorDTO);
return authorDTO;
}
#Override
public AuthorDTO updateAuthor(String authorId, AuthorDTO authorDTO) {
Author author = authorRepository.findById(authorId).orElseThrow(EntityNotFoundException:: new);
BeanUtils.copyProperties(authorDTO,author);
authorRepository.save(author);
BeanUtils.copyProperties(author, authorDTO);
return authorDTO;
}
#Override
public AuthorDTO getAuthorById(String authorId) {
Author author = authorRepository.findById(authorId).orElseThrow(EntityNotFoundException :: new);
AuthorDTO authorDTO = new AuthorDTO();
BeanUtils.copyProperties(author, authorDTO);
return authorDTO;
}
#Override
public Page<Author> getAllAuthors(int page, int size) {
Pageable pageable = PageRequest.of(page,size);
return authorRepository.findAll(pageable);
}
#Override
public void deleteAuthorById(String authorId) {
authorRepository.deleteById(authorId);
}
}
This is User class, which serves as the Entity.
package com.userproject.Entities;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
#Entity
#Table(name = "userservice")
public class User {
#Id
#Column(name="userID")
int userId;
#Column(name="username")
String username;
#Column(name="age")
int age;
public User(int userId, String username, int age) {
super();
this.userId = userId;
this.username = username;
this.age = age;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
#Override
public String toString() {
return "User [userId=" + userId + ", username=" + username + ", age=" + age + "]";
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
This is my repository interface
package com.userproject.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import com.userproject.Entities.User;
public interface UserRepository extends JpaRepository<User, Integer> {
public User findById(int id);
}
This is my Service class
package com.userproject.Service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.userproject.Entities.User;
import com.userproject.dao.UserRepository;
#Service
public class UserService {
#Autowired
private UserRepository userRepository;
public User addUser(User usr) {
User savedUser = this.userRepository.save(usr);
return savedUser;
}
public List<User> getAllInfo(){
Iterable<User> allUsers = this.userRepository.findAll();
return (List<User>)allUsers;
}
public User getUser(int usrId) {
User usr = this.userRepository.findById(usrId);
if (usr == null)
throw new NullPointerException();
return usr;
}
}
This is my Controller
package com.userproject.Controllers;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.userproject.Entities.User;
import com.userproject.Service.UserService;
#RestController
#RequestMapping("/user")
public class UserController {
#Autowired
private UserService service;
#PostMapping("/add")
public ResponseEntity<User> addUser(#RequestBody User u){
try {
User addUser = this.service.addUser(u);
return ResponseEntity.ok(addUser);
} catch(Exception e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
#GetMapping("/{id}")
public ResponseEntity<User> getUserById(#PathVariable("id") int userID){
try {
User u = this.service.getUser(userID);
return ResponseEntity.ok(u);
} catch(NullPointerException e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
#GetMapping("/all")
public ResponseEntity<List<User>> getAllUsers(){
try {
return ResponseEntity.ok(this.service.getAllInfo());
} catch(Exception e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
}
This is my main application class
package com.userproject;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#EnableJpaRepositories("com.userproject.dao")
#SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class UserProjectApplication {
public static void main(String[] args) {
SpringApplication.run(UserProjectApplication.class, args);
}
}
This is application.properties file
spring.jpa.database=mysql
spring.datasource.username=*****
spring.datasource.password=*****
spring.datasource.url=jdbc:mysql://*******:3306/practice
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
spring.jooq.sql-dialect = org.hibernate.dialect.MySQL57Dialect
spring.jpa.hibernate.ddl-auto= update
This is my project structure:
(https://i.stack.imgur.com/UR10B.png)
When I try to run the application, I keep getting the following message: `
Description:
Field userRepository in com.userproject.Service.UserService required a bean named 'entityManagerFactory' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean named 'entityManagerFactory' in your configuration.
If I remove the "exclude" parameter from #SpringBootApplication, it throws an error stating the datasource cannot be configured as the url is missing.
If I remove the #EnableJpaRepositories, it throws an error stating my userRepository field in Service class cannot be configured.
From what I understand, this whole problem arises from me trying to autowire the userRepository field (which is actually an interface) in the Service class. However, SpringBoot shall be able to do that with the help of proxy classes.
Please provide me with a solution to this.
While there is user in the database, another user with exactly the same credentials is "successfully" inserted in the database...
Hello! I'm building my own ecommerce app and I included spring security. Now, while I was developing security part of the app, I tried it to see if it's working and once I entered desired info in the request body, for the first request the user was successfully inserted in the database, but when I tried to do it the second time, to check if the userExists which throws and error that user is already registered, works, it just added another user with the same credentials (name, lastname, mail and so). I go to userRepository to check if there is already the user with the same email, it makes sense what i wrote, but it doesnt work...Please help...Here are all the files:
EDIT : Mistakenly copied UserRegistrationController twice...So here is the userService.java:
package com.marin.thrift.service;
import com.marin.thrift.dao.UserRepository;
import com.marin.thrift.entity.User;
import lombok.AllArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
#Service
#AllArgsConstructor
public class UserService implements UserDetailsService {
private final UserRepository userRepository;
private final static String USER_NOT_FOUND = "user with email %s not found";
private final BCryptPasswordEncoder bCryptPasswordEncoder;
#Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
return userRepository.findByUsername(email).orElseThrow(()-> new UsernameNotFoundException(String.format(USER_NOT_FOUND, email)));
}
public String singUpUser(User user){
boolean userExists = userRepository.findByUsername(user.getEmail()).isPresent();
if(userExists){
return "user already in place";
}
String encodedPassword = bCryptPasswordEncoder.encode(user.getPassword());
user.setPassword(encodedPassword);
userRepository.save(user);
return "it works";
}
}
package com.marin.thrift.registration;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping(path = "api/v1/registration")
#AllArgsConstructor
public class UserRegistrationController {
private RegistrationService registrationService;
#PostMapping
public String register(#RequestBody registrationRequest request){
return registrationService.register(request);
}
}
package com.marin.thrift.registration;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping(path = "api/v1/registration")
#AllArgsConstructor
public class UserRegistrationController {
private RegistrationService registrationService;
#PostMapping
public String register(#RequestBody registrationRequest request){
return registrationService.register(request);
}
}
package com.marin.thrift.registration;
import com.marin.thrift.entity.Role;
import com.marin.thrift.entity.User;
import com.marin.thrift.service.UserService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
#Service
#AllArgsConstructor
public class RegistrationService {
private final EmailValidator emailValidator;
private final UserService userService;
public String register(registrationRequest request) {
Boolean isValidEmail = emailValidator.test(request.getEmail());
if (!isValidEmail){
throw new IllegalStateException("Email is not valid");
}
return userService.singUpUser(new User(request.getFirstName(), request.getLastName(),
request.getPassword(), request.getEmail(), Role.USER));
}
}
package com.marin.thrift.entity;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.*;
import java.util.Collection;
import java.util.Date;
#Entity
#Data
#Table(name = "users")
public class User implements UserDetails {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "date_of_birth")
private Date dateOfBirth;
#Column(name = "username")
private String username;
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
private Role role;
private Boolean locked = false;
private Boolean enabled = false;
public User(String firstName, String lastName, String password, String email, Role role) {
this.firstName = firstName;
this.lastName = lastName;
this.password = password;
this.email = email;
this.role = role;
}
public User() {
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(role.name());
return null;
}
#Override
public String getPassword() {
return password;
}
#Override
public String getUsername(){
return email;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return !locked;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return enabled;
}
}
package com.marin.thrift.security.config;
import com.marin.thrift.service.UserService;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
#Configuration
#AllArgsConstructor
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final UserService userService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
#Override
protected void configure(HttpSecurity http) throws Exception{
http.csrf()
.disable().authorizeRequests()
.antMatchers("/api/v*/registration/**").permitAll()
.anyRequest().authenticated().and().formLogin();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.authenticationProvider(daoAuthenticationProvider());
}
#Bean
public DaoAuthenticationProvider daoAuthenticationProvider(){
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setPasswordEncoder(bCryptPasswordEncoder);
provider.setUserDetailsService(userService);
return provider;
}
}
package com.marin.thrift.registration;
import lombok.*;
#Getter
#AllArgsConstructor
#EqualsAndHashCode
#ToString
public class registrationRequest {
private final String firstName;
private final String lastName;
private final String password;
private final String email;
}
Without UserService it's hard to say what is happen. But if I see your jpa mapping I can guess that if you want unique entry per unique user, you have to delete generated column id. And instead you have to put #Id annotation on email. In this case you need also make changes in sql table.
Or as alternative you can stay by current mapping and simply conduct findByEmail before save entity. And if Optional is not empty - then user is already in database registred.
I just fixed my mistake. The mistake was in the database where I forgot to set email as unique. Once I did that, the code works perfectly.
I finished creating a simple Spring-boot project in which I can enter users and through the Get command it returns me the name (from a list of identical names) with the oldest entry date. Unfortunately, every time I ask for Get it returns this ERROR:
D:\>curl -G localhost:8080/demo/first?=Biagio
{"timestamp":"2020-10-04T22:46:35.996+00:00","status":404,"error":"Not Found","message":"","path":"/demo/first"}
And to each of my POST / Add requests like this ERROR:
D:\>curl localhost:8080/demo/add -d name=Giovanni -d email=giovanni#gmail.com -d surname=Jackie
{"timestamp":"2020-10-04T22:40:51.928+00:00","status":404,"error":"Not Found","message":"","path":"/demo/add"}
Below I enter the interested parties of my project to try to get something out of it, because I have been stuck for days now
AccessingDataMysqlApplication.java
package com.example.accessingdatamysql;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
public class AccessingDataMysqlApplication {
public static void main(String[] args) {
SpringApplication.run(AccessingDataMysqlApplication.class, args);
}
}
MainController.java
package com.example.accessingdatamysql.rest;
import javax.persistence.NoResultException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.example.accessingdatamysql.model.UserDto;
import com.example.accessingdatamysql.service.UserService;
#RestController
#RequestMapping("/demo")
public class MainController {
#Autowired
private UserService userService;
#Transactional
//#RequestMapping(value = "/add/", method = RequestMethod.POST)
#PostMapping(path="/demo/add")
public String addNewUser(#PathVariable("name") String name, #PathVariable("email") String email,
#PathVariable("surname") String surname) {
UserDto n = new UserDto();
n.setName(name);
n.setSurname(surname);
n.setEmail(email);
userService.create(n);
return "User Saved in DB";
}
#SuppressWarnings({ "rawtypes", "unchecked" })
//#RequestMapping(value = "/fetchUser/{name}", method = RequestMethod.GET)
#GetMapping("/demo/first")
public ResponseEntity<UserDto> fetchUser(#PathVariable("name") String name) {
System.out.println(name);
try {
UserDto namefound = userService.findFirstByName(name);
System.out.println("Name found");
ResponseEntity<UserDto> user = new ResponseEntity<UserDto>(namefound, HttpStatus.OK);
return user;
} catch(NoResultException ne) {
System.out.println("User not found");
return new ResponseEntity("User not found with name : " + name, HttpStatus.NOT_FOUND);
}
}
}
UserService.java
package com.example.accessingdatamysql.service;
import org.springframework.stereotype.Service;
import com.example.accessingdatamysql.model.UserDto;
#Service
public interface UserService {
UserDto findFirstByName(String name);
void create(UserDto user);
}
UserServiceImpl.java
package com.example.accessingdatamysql.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import com.example.accessingdatamysql.model.UserDto;
import com.example.accessingdatamysql.model.UserEntity;
import com.example.accessingdatamysql.repo.UserRepository;
import com.example.accessingdatamysql.util.UserMapper;
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserRepository userRepository;
#Autowired
UserMapper mapper;
#Override
public UserDto findFirstByName(String name) {
UserEntity entity = userRepository.findFirstByName(name);
return mapper.toDtoMapper(entity);
}
#Override
public void create(UserDto user) {
UserEntity entity = mapper.toEntityMapper(user);
userRepository.create(entity);
}
}
UserMapper.java
package com.example.accessingdatamysql.util;
import org.mapstruct.Mapper;
import com.example.accessingdatamysql.model.UserDto;
import com.example.accessingdatamysql.model.UserEntity;
#Mapper(componentModel = "spring")
public interface UserMapper {
public UserEntity toEntityMapper (UserDto user);
public UserDto toDtoMapper (UserEntity userEntity);
}
UserRepository.java
package com.example.accessingdatamysql.repo;
import org.springframework.stereotype.Repository;
import com.example.accessingdatamysql.model.UserEntity;
#Repository
public interface UserRepository {
UserEntity findFirstByName(String name);
void create(UserEntity entity);
}
UserRepositoryImpl.java
package com.example.accessingdatamysql.service;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.springframework.stereotype.Component;
import com.example.accessingdatamysql.model.UserEntity;
import com.example.accessingdatamysql.repo.UserRepository;
#Component
public class UserRepositoryImpl implements UserRepository {
private final EntityManager em;
public UserRepositoryImpl(EntityManager entityManager) {
this.em = entityManager;
}
#Override
public UserEntity findFirstByName(String name) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<UserEntity> criteria = builder.createQuery(UserEntity.class);
Root<UserEntity> root = criteria.from(UserEntity.class);
criteria.select(root).where(builder.equal(root.get("name"), name));
criteria.orderBy(builder.asc(root.get("timestamp")));
TypedQuery<UserEntity> query = em.createQuery(criteria).setMaxResults(1);
return query.getSingleResult();
}
#Override
// per la creazione//
public void create(UserEntity entity) {
em.persist(entity);
}
}
UserDto.java
package com.example.accessingdatamysql.model;
import java.io.Serializable;
import java.sql.Timestamp;
public class UserDto implements Serializable {
/**
*
*/
private static final long serialVersionUID = -7621330660870602403L;
/**
*
*/
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Timestamp getTimestamp() {
return timestamp;
}
public void setTimestamp(Timestamp timestamp) {
this.timestamp = timestamp;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
private Timestamp timestamp;
private String email;
private String surname;
}
If you need I can also insert User.java and the pom, but the pom has no problems as the dependencies are all correct.
You have an additional demo in your path descriptions for GET and POST methods, you should remove it:
#GetMapping("/demo/first")
#PostMapping(path = "/demo/first")
It should be :
#GetMapping("/first")
#PostMapping(path = "/first")
This because you have already defined demo in the RequestMapping annotation in the class level.
This question already has answers here:
Springboot Security hasRole not working
(3 answers)
Closed 4 years ago.
I am using spring security in my spring boot app.
My app works well with in-memory authentication.
But when users are loaded from the database it does not authenticate. It returns 403 access denied error code. UserDetailsService is able to fetch the user information from the database but I dont know where it is going wrong. I am new to spring.
here is my complete code related to security
User.java
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import lombok.Data;
#Entity
#Table(name = "user")
#Data
public class User {
#Id
#NotNull
#GeneratedValue(strategy = GenerationType.AUTO)
private Long userId;
#Column(name = "USERNAME", unique = true)
#NotNull
private String username;
#Column(name = "PASSWORD")
#NotNull
private String password;
#Column(name = "DISPLAY_NAME")
private String displayName;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "id")
private Set<Role> userRoles;
private String profilePicturePath;
}
Role.java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
#Entity
#Table(name = "roles")
#Data
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String role;
}
UserRepository.java
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.cloudsofts.cloudschool.people.users.pojos.User;
#Repository("userRepository")
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
RoleRepository.java
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.cloudsofts.cloudschool.people.users.pojos.Role;
#Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
}
UserService.java
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import com.cloudsofts.cloudschool.people.users.pojos.User;
import com.cloudsofts.cloudschool.people.users.repositories.UserRepository;
#Service
public class UserService {
#Autowired
UserRepository userRep;
#Autowired
private PasswordEncoder passwordEncoder;
public List<User> getAllUsers() {
List<User> users = userRep.findAll();
return users;
}
public void addUser(User user) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
userRep.save(user);
}
public void updateUser(User user) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
userRep.save(user);
}
public void deleteUser(Long id) {
userRep.delete(id);
}
public User getUser(Long id) {
return userRep.findOne(id);
}
}
RoleService.java
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.cloudsofts.cloudschool.people.users.pojos.Role;
import com.cloudsofts.cloudschool.people.users.repositories.RoleRepository;
#Service
public class RoleService {
#Autowired
RoleRepository userRoleRep;
public void addUserRole(Role role) {
userRoleRep.save(role);
}
public void updateUserRole(Role role) {
userRoleRep.save(role);
}
public void deleteUserRole(Long id) {
userRoleRep.delete(id);
}
public Role getUserRole(Long id) {
return userRoleRep.findOne(id);
}
public List<Role> getAllUserRoles() {
return userRoleRep.findAll();
}
}
CustomUserDetails.java
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import lombok.Data;
#Data
public class CustomUserDetails implements UserDetails {
private static final long serialVersionUID = 1L;
private User user;
public CustomUserDetails(final User user) {
this.user = user;
}
public CustomUserDetails() {
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
final Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
Set<Role> roles = null;
if (user != null) {
roles = user.getUserRoles();
}
if (roles != null) {
for (Role role : roles) {
authorities.add(new SimpleGrantedAuthority(role.getRole()));
}
}
return authorities;
}
#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;
}
}
CustomUserDetailsService.java
import org.springframework.beans.factory.annotation.Autowired;
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 com.cloudsofts.cloudschool.people.users.pojos.CustomUserDetails;
import com.cloudsofts.cloudschool.people.users.pojos.Role;
import com.cloudsofts.cloudschool.people.users.pojos.User;
import com.cloudsofts.cloudschool.people.users.repositories.UserRepository;
#Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(username);
} else {
System.out.println("______________________________________________________________");
System.out.println("username: " + user.getUsername());
System.out.println("password: " + user.getPassword());
System.out.println("Roles: ");
for (Role role : user.getUserRoles()) {
System.out.println(role.getRole());
}
System.out.println("______________________________________________________________");
return new CustomUserDetails(user);
}
}
}
SecurityConfig.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.cloudsofts.cloudschool.security.CustomUserDetailsService;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Qualifier("userDetailsService")
#Autowired
CustomUserDetailsService userDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
try {
auth.userDetailsService(this.userDetailsService).passwordEncoder(passwordEncoder());
System.out.println("_________________________________________________");
String username = SecurityContextHolder.getContext().getAuthentication().getName();
System.out.println("_________________________________________________");
System.out.println("You have logged in as " + username);
System.out.println("_________________________________________________");
} catch (Exception e) {
System.out.println("_________________________________________________");
System.out.println(e.getMessage());
System.out.println("_________________________________________________");
}
}
#Bean(name = "passwordEncoder")
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/*
* #Autowired public void configureGlobal(AuthenticationManagerBuilder auth)
* throws Exception {
* auth.inMemoryAuthentication().withUser("student").password("student").roles(
* "student").and().withUser("admin") .password("admin").roles("admin"); }
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
// http.authorizeRequests().anyRequest().permitAll();
// http.authorizeRequests().antMatchers("/api/**").permitAll();
http.authorizeRequests().antMatchers("/student/**").hasAnyRole("student", "admin");
http.authorizeRequests().antMatchers("/api/admin/**").hasRole("admin");
http.authorizeRequests().antMatchers("/library/**").hasAnyRole("librarian", "admin");
http.httpBasic();
// http.formLogin().and().logout().logoutSuccessUrl("/login?logout").permitAll();
}
}
Screenshots
Postman Screenshot
Browser Screenshot
Users in the db
Roles in the db
User-Role mapping
Console output after giving the credentials
You seems to using the BCryptPasswordEncoder to encrypt and decrypt password. But 'Users' table screenshot shows the password in plain text. Can you validate the place where you are saving or updating the user, it is actually encoding the password and also the password encoder bean is of type 'BCryptPasswordEncoder'
I got the problem solved.
I had to add ROLE_ as a prefix to the roles.
Now everything works fine