I've created a spring boot app with spring-data-rest.
My Rest API is working just fine. Then I imported the spring security. I've also done configurations after referring to a number of Web resources.
However, each time I send a request, I get Bad Credential Error The below are my codes
User.java
package com.innaun.model;
import org.springframework.data.rest.core.annotation.RestResource;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.HashSet;
import java.util.Set;
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long userId;
#Column(unique = true, nullable = false)
private String username;
#NotNull
#RestResource(exported = false )
private String password;
#NotNull
private boolean enabled;
#OneToMany
private Set<UserRole> userRoles = new HashSet<UserRole>(0);
public User() {
}
public User(String username, String password, boolean enabled) {
this.username = username;
this.password = password;
this.enabled = enabled;
}
public Set<UserRole> getUserRoles() {
return userRoles;
}
public void setUserRoles(Set<UserRole> userRoles) {
this.userRoles = userRoles;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
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 boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
UserRole.java
package com.innaun.model;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
#Entity
public class UserRole {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long userRoleId;
#NotNull
private String userRole;
#ManyToOne
private User user;
public UserRole() {
}
public UserRole(String userRole, User user) {
this.userRole = userRole;
this.user = user;
}
public Long getUserRoleId() {
return userRoleId;
}
public void setUserRoleId(Long userRoleId) {
this.userRoleId = userRoleId;
}
public String getUserRole() {
return userRole;
}
public void setUserRole(String userRole) {
this.userRole = userRole;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
UserRepository.java
package com.innaun.model;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
#RepositoryRestResource
public interface UserRepository extends CrudRepository<User, Long>{
User findByUsername(#Param("user") String user);
}
UserRoleRepository.java
package com.innaun.model;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
#RepositoryRestResource
public interface UserRoleRepository extends CrudRepository<UserRole, Long> {
}
AppUserDetailsService.java
package com.innaun.model;
import com.innaun.model.UserRepository;
import com.innaun.model.UserRole;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
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 javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
#Service("appUserDetailsService")
public class AppUserDetailsService implements UserDetailsService {
#Autowired
private UserRepository userRepository;
#Transactional
#Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
com.innaun.model.User user = userRepository.findByUsername(s);
List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRoles());
return buildUserForAuthentication(user, authorities);
}
private User buildUserForAuthentication(com.innaun.model.User user, List<GrantedAuthority> authorities){
return new User(user.getUsername(), user.getPassword(), user.isEnabled(), true, true, true, authorities);
}
private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles){
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
for (UserRole userRole : userRoles){
setAuths.add(new SimpleGrantedAuthority(userRole.getUserRole()));
}
List<GrantedAuthority> result = new ArrayList<GrantedAuthority>(setAuths);
return result;
}
}
ApplicationRESTSecurity.java
package com.innaun;
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.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
#Configuration
#EnableWebSecurity
public class ApplicationRESTSecurity extends WebSecurityConfigurerAdapter {
#Qualifier("appUserDetailsService")
#Autowired
UserDetailsService userDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception{
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and().httpBasic()
.and().csrf()
.disable();
}
}
Also, I've added the below to add a test user to the database
package com.innaun;
import com.innaun.model.User;
import com.innaun.model.UserRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
#SpringBootApplication
public class PitchuApplication {
public static void main(String[] args) {
SpringApplication.run(PitchuApplication.class, args);
}
#Bean
CommandLineRunner init(UserRepository userRepository) {
return (args) -> {
userRepository.save(new User("myuser", "mypassword", true));
};
}
}
Just as I thought, the database now has the above user and the user is enabled.
Screenshot of the User data table
All the other tables are blank.
However when I tried the curl
curl -u myuser:mypassword localhost:8080
it returned
{"timestamp":1489090315435,"status":401,"error":"Unauthorized","message":"Bad credentials","path":"/"}
Can anyone explain where did I went wrong.
Your configuration looks fine to me. So, my best guess is that your password column in your database has length less than 60 which is the length of the hash BCrypt will produce.
I figured it out. And this was so simple mistake. the password I used to save a new user in the userRepository is raw instead of encrypted. I figured it out by:
//Create a new password encoder
private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
//Encode the password
String password = "mypassword";
String hashedPassword = passwordEncoder.encode(password);
//Create the user with the encoded password
User user = new User(myuser, hashedPassword, true);
//then persist
userRepository.save(user);
Related
I am using spring boot v2.5.2. Below is my folder structure and code. This is simple test project.
My folder structure:
RESTController Class:
package com.user.UserManagementSystem.controller;
import com.user.UserManagementSystem.model.User;
import com.user.UserManagementSystem.service.UserServiceImpl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping("/api/v1/")
public class UserController {
#Autowired
private UserServiceImpl userRepository;
#GetMapping("/getAllUsers")
public List<User> getAllUsers() {
return userRepository.getUsers();
}
#GetMapping("/")
public String home() {
return "Hello";
}
}
User.java
package com.user.UserManagementSystem.model;
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(name= "Users")
public class User {
public User() {
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name ="userName")
private String userName;
#Column(name ="name")
private String name;
#Column(name ="language")
private String language;
#Column(name ="mobileNumber")
private int mobileNumber;
public User(String userName, String name, String language, int mobileNumber) {
this.userName = userName;
this.name = name;
this.language = language;
this.mobileNumber = mobileNumber;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public int getMobileNumber() {
return mobileNumber;
}
public void setMobileNumber(int mobileNumber) {
this.mobileNumber = mobileNumber;
}
}
UserRepository.java
package com.user.UserManagementSystem.repository;
import com.user.UserManagementSystem.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface UserRepository extends JpaRepository<User, Long>{
}
UserService.java
package com.user.UserManagementSystem.service;
import com.user.UserManagementSystem.model.User;
import java.util.List;
public interface UserService {
List<User> getUsers();
User getUserById(Long id);
User addUser(User user);
void deleteUser(Long id);
}
UserServiceImpl.java
package com.user.UserManagementSystem.service;
import com.user.UserManagementSystem.repository.UserRepository;
import com.user.UserManagementSystem.model.User;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class UserServiceImpl implements UserService{
#Autowired
UserRepository userRepository;
#Override
public List<User> getUsers() {
return userRepository.findAll();
}
#Override
public User getUserById(Long id) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public User addUser(User user) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void deleteUser(Long id) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
UserManangmentSystemApplication.java
package com.user.UserManangmentSystem;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication(scanBasePackages = {"com.user.UserManangmentSystem", "com.user.UserManagementSystem.controller", "com.user.UserManagementSystem.repository", "com.user.UserManagementSystem.service"})
//#SpringBootApplication
public class UserManangmentSystemApplication {
public static void main(String[] args) {
SpringApplication.run(UserManangmentSystemApplication.class, args);
}
}
application.properties:
spring.datasource.url=jdbc:mariadb://localhost:3306/ums
spring.datasource.username=ums
spring.datasource.password=ums
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDB53Dialect
server.port=8888
debug=true
When it build the project i am getting :
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.user.UserManagementSystem.repository.UserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1790) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1346) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.8.jar:5.3.8]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657) ~[spring-beans-5.3.8.jar:5.3.8]
Thanks in Advance.
Typo in your base package name which makes packages different.
Change
com.user.UserManangmentSystem
To
com.user.UserManangementSystem
Correct management spelling.
You have correct package structure it will collect all bean within base package and sub package also. No need explicitly mention package scan. If you have any spell mistakes then that error will occur.
I'm trying to build a spring boot rest API with JWT role-based authentication, I'm stuck at the login part in spring security.
I'm currently using spring boot, spring data JPA (hibernate under the hood ), and Oracle 11g database.
All the tables get created and I can sign up but can't login.
WebSecurityConfig.java
import org.springframework.context.annotation.*;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.dao.*;
import org.springframework.security.config.annotation.authentication.builders.*;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.*;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private UserDetailsServiceImpl userDetailsService;
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Bean
public UserDetailsService userDetailsService() {
return new UserDetailsServiceImpl();
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.POST,"/users/**").permitAll()
.antMatchers("/roles").hasAnyAuthority("ADMIN")
.anyRequest().authenticated()
.and().addFilter(new JWTAuthorizationFilter(authenticationManager()))
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
// this disables session creation on Spring Security
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
UserDetails.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
public class UserDetails implements org.springframework.security.core.userdetails.UserDetails {
private User user;
#Autowired
private UsersRepository usersRepository;
public UserDetails(UsersRepository usersRepository) {
this.usersRepository = usersRepository;
}
public UserDetails(User user) {
this.user = user;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<Role> roles = user.getRoles();
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
for (Role role : roles) {
authorities.add(new SimpleGrantedAuthority(role.getName()));
}
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 user.isEnabled();
}
}
UserDetailsServiceImpl.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private UsersRepository usersRepository;
#Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = usersRepository.getUserByUsername(username);
System.out.println("Found user in repo : "+user.getUsername()+" "+user.getPassword()+" "+user.getRoles());
if (user == null) {
throw new UsernameNotFoundException("Could not find user");
}
return new UserDetails(user);
}
}
JWTAuthenticationFilter.java
import com.auth0.jwt.JWT;
import com.bte.ifrs_server.entities.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import static com.auth0.jwt.algorithms.Algorithm.HMAC512;
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Override
public Authentication attemptAuthentication(HttpServletRequest req,
HttpServletResponse res) throws AuthenticationException {
System.out.println("Attempting authentication");
try {
User creds = new ObjectMapper()
.readValue(req.getInputStream(), User.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
creds.getUsername(),
creds.getPassword(),
new ArrayList<>())
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
protected void successfulAuthentication(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain,
Authentication auth) throws IOException, ServletException {
System.out.println("Successfull Auth !!");
String token = JWT.create()
.withSubject(((User) auth.getPrincipal()).getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.sign(HMAC512(SECRET.getBytes()));
//Printing the access token into the response
PrintWriter out = res.getWriter();
res.setContentType("application/json");
res.setCharacterEncoding("UTF-8");
//Creating access token object to return it as a response
AccessToken accessToken=new AccessToken(HEADER_STRING,TOKEN_PREFIX,token);
//Set the access token as a JSON response body
Gson gson = new Gson();
String access_token=gson.toJson(accessToken);
out.print(access_token);
out.flush();
//Adding the access token to response header
res.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
}
}
JWTAuthorizationFilter.java
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
public JWTAuthorizationFilter(AuthenticationManager authManager) {
super(authManager);
}
#Override
protected void doFilterInternal(HttpServletRequest req,
HttpServletResponse res,
FilterChain chain) throws IOException, ServletException {
String header = req.getHeader(HEADER_STRING);
if (header == null || !header.startsWith(TOKEN_PREFIX)) {
chain.doFilter(req, res);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(req);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(req, res);
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
String token = request.getHeader(HEADER_STRING);
if (token != null) {
// parse the token.
String user = JWT.require(Algorithm.HMAC512(SECRET.getBytes()))
.build()
.verify(token.replace(TOKEN_PREFIX, ""))
.getSubject();
if (user != null) {
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}
return null;
}
return null;
}
}
AccessToken.java
public class AccessToken {
String header,prefix,value;
public AccessToken(String header, String prefix, String value) {
this.header = header;
this.prefix = prefix;
this.value = value;
}
}
SecurityConstants.java
import java.util.Arrays;
import java.util.List;
public class SecurityConstants {
public static final String SECRET = "SecretKeyToGenJWTs";
public static final long EXPIRATION_TIME = 864_000_000; // 10 days
public static final String TOKEN_PREFIX = "Bearer ";
public static final String HEADER_STRING = "Authorization";
public static final String SIGN_UP_URL = "/users/sign-up";
public static final List<String> PUBLIC_ROUTES = Arrays.asList("/users/sign-up" , "/users/login" , "/roles/**");
}
Role.java
import javax.persistence.*;
#Entity
#Table(name = "roles")
public class Role {
#Id
#Column(name = "role_id")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_generator")
#SequenceGenerator(name="id_generator", sequenceName = "role_id_sequence",allocationSize = 1)
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
User.java
import java.util.*;
import javax.persistence.*;
#Entity
#Table(name = "users")
public class User {
#Id
#Column(name = "user_id")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_generator")
#SequenceGenerator(name="id_generator", sequenceName = "user_id_sequence",allocationSize = 1)
private Long id;
private String username;
private String password;
private boolean enabled;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(
name = "users_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
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 boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
and the main app:
IfrsServerApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#EnableJpaRepositories
#SpringBootApplication
public class IfrsServerApplication {
public static void main(String[] args) {
SpringApplication.run(IfrsServerApplication.class, args);
}
}
The code compiles and the server runs I can signup but authentication returns 403 after attempting to login ('/login').
Any Help will be appreciated. Thanks in advance.
You've shared quite a bit of code, so there may be other issues here, but one that I'll point out is that in your JWTAuthorizationFilter, you are not granting any authorities to the user:
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
The last parameter is what authorities the user has.
Configurations like:
.antMatchers("/roles").hasAnyAuthority("ADMIN")
will always return a 403 in that case.
The first solution I'd recommend is using Spring Security's built-in support for JWTs instead of rolling your own. There's a JWT login sample that looks quite similar to what you are trying to achieve.
Alternatively, you can try changing how you are calling that constructor so that you grant a list of authorities (like new SimpleGrantedAuthority("ADMIN")). The downside here is that you'll have a lot more code to maintain.
I am trying to add to website I created a requirement for user to be logged-in in order to access content and also split 3 types of users: non logged-in person, admin and standard user. I struggle a lot with it as I was unable to find a guide that would both explain it to me and work properly at the same time. Could you guys please help me and tell em what am I doing wrong? I spent 6 days trying to get this logging in feature to work and I feel compleatly lost at this point because I tried so many different codes and approaches from guides I found. As for my database I am using SQL Workbench.
The problem is (at least I think this is the problem) that in SecurityConfig in configure method I am not actually passing Role of the User (hasAnyRole('Admin')). I was trying to do it in many ways but I don't really udnerstand how am I supposed to pass Role to it.
Here is my controller package:
MainController:
package Projekt.ProjektAI.controller;
import Projekt.ProjektAI.entities.Book;
import Projekt.ProjektAI.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import java.security.Provider;
import java.util.List;
#Controller
public class MainController {
private BookService service;
#Autowired
public MainController(BookService service){
this.service = service;
}
#RequestMapping("/")
public String viewNormalHomePage(Model model) {
List<Book> listBooks = service.listAll();
model.addAttribute("listBooks", listBooks);
return "indexNormal";
}
#RequestMapping("/admin")
public String viewAdminHomePage(Model model) {
List<Book> listBooks = service.listAll();
model.addAttribute("listBooks", listBooks);
return "index";
}
#RequestMapping("/user")
public String viewUserHomePage(Model model) {
List<Book> listBooks = service.listAll();
model.addAttribute("listBooks", listBooks);
return "indexStandard";
}
#RequestMapping("/admin/new")
public String showNewBookPage(Model model) {
Book book = new Book();
model.addAttribute("book", book);
return "newBook";
}
#RequestMapping("/admin/edit/{id}")
public ModelAndView showEditBookPage(#PathVariable(name = "id") Long id) {
ModelAndView mav = new ModelAndView("editBook");
Book book = service.get(id);
mav.addObject("book", book);
return mav;
}
#RequestMapping(value = "/admin/save", method = RequestMethod.POST)
public String saveBook(#ModelAttribute("book") Book book) {
service.save(book);
return "redirect:/";
}
#RequestMapping("/admin/delete/{id}")
public String deleteBook(#PathVariable(name = "id") Long id) {
service.delete(id);
return "redirect:/";
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(Model model) {
return "login";
}
#RequestMapping(value = "/user", method = RequestMethod.GET)
public String userIndex() {
return "user/index";
}
}
UserRegistrationController:
package Projekt.ProjektAI.controller;
import javax.validation.Valid;
import Projekt.ProjektAI.service.UserService;
import Projekt.ProjektAI.registrationDTO.UserRegistrationDTO;
import Projekt.ProjektAI.entities.User;
import org.springframework.beans.factory.annotation.Autowired;
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 org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping("/registration")
public class UserRegistrationController {
#Autowired
private UserService userService;
#ModelAttribute("user")
public UserRegistrationDTO userRegistrationDto() {
return new UserRegistrationDTO();
}
#GetMapping
public String showRegistrationForm(Model model) {
return "registration";
}
#PostMapping
public String registerUserAccount(#ModelAttribute("user") #Valid UserRegistrationDTO userDto,
BindingResult result) {
User existing = userService.findByEmail(userDto.getEmail());
if (existing != null) {
result.rejectValue("email", null, "There is already an account registered with that email");
}
if (result.hasErrors()) {
return "registration";
}
userService.save(userDto);
return "redirect:/registration?success";
}
}
Entities package:
Book entity:
package Projekt.ProjektAI.entities;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
#Entity
#Getter
#Setter
public class Book {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String autor;
#Column
private String tytul;
#Column
private String gatunek;
#Column
private float cena;
public Book() {
}
#Override
public String toString() {
return "Book{" +
"id=" + id +
", autor='" + autor + '\'' +
", tytul='" + tytul + '\'' +
", gatunek='" + gatunek + '\'' +
", cena=" + cena +
'}';
}
}
Role entity:
package Projekt.ProjektAI.entities;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
#Getter
#Setter
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
protected Role() {}
public Role(String name) {
this.name = name;
}
#Override
public String toString() {
return "Role{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
User entity:
package Projekt.ProjektAI.entities;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import java.util.Collection;
#Entity
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#Table(uniqueConstraints = #UniqueConstraint(columnNames = "email"))
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
private String email;
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 Collection <Projekt.ProjektAI.entities.Role> roles;
public Collection <Projekt.ProjektAI.entities.Role> getRoles() {
return roles;
}
public void setRoles(Collection <Projekt.ProjektAI.entities.Role> roles) {
this.roles = roles;
}
#Override
public String toString() {
return "User{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", password='" + "*********" + '\'' +
", roles=" + roles +
'}';
}
}
registration DTO package:
FieldMatch interface:
package Projekt.ProjektAI.registrationDTO;
import javax.validation.Payload;
import javax.validation.Constraint;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
#Target({
TYPE,
ANNOTATION_TYPE
})
#Retention(RUNTIME)
#Constraint(validatedBy = FieldMatchValidator.class)
#Documented
public #interface FieldMatch {
String message() default "{constraints.field-match}";
Class < ? > [] groups() default {};
Class < ? extends Payload > [] payload() default {};
String first();
String second();
#Target({
TYPE,
ANNOTATION_TYPE
})
#Retention(RUNTIME)
#Documented
#interface List {
FieldMatch[] value();
}
}
Field Match Validator:
package Projekt.ProjektAI.registrationDTO;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.apache.commons.beanutils.BeanUtils;
public class FieldMatchValidator implements ConstraintValidator <Projekt.ProjektAI.registrationDTO.FieldMatch, Object > {
private String firstFieldName;
private String secondFieldName;
#Override
public void initialize(final Projekt.ProjektAI.registrationDTO.FieldMatch constraintAnnotation) {
firstFieldName = constraintAnnotation.first();
secondFieldName = constraintAnnotation.second();
}
#Override
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
try {
final Object firstObj = BeanUtils.getProperty(value, firstFieldName);
final Object secondObj = BeanUtils.getProperty(value, secondFieldName);
return firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
} catch (final Exception ignore) {}
return true;
}
}
User Registration DTO:
package Projekt.ProjektAI.registrationDTO;
import lombok.Getter;
import lombok.Setter;
import javax.validation.Valid;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;
#Projekt.ProjektAI.registrationDTO.FieldMatch.List({
#Projekt.ProjektAI.registrationDTO.FieldMatch(first = "password", second = "confirmPassword", message = "The password fields must match"),
#Projekt.ProjektAI.registrationDTO.FieldMatch(first = "email", second = "confirmEmail", message = "The email fields must match")
})
#Getter
#Setter
public class UserRegistrationDTO {
#NotEmpty
private String firstName;
#NotEmpty
private String lastName;
#NotEmpty
private String password;
#NotEmpty
private String confirmPassword;
#Email
#NotEmpty
private String email;
#Email
#NotEmpty
private String confirmEmail;
#AssertTrue
private Boolean terms;
}
repositories package:
Book Repository
package Projekt.ProjektAI.repositories;
import Projekt.ProjektAI.entities.Book;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface BookRepository extends JpaRepository<Book, Long> {
}
User Repository:
package Projekt.ProjektAI.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import Projekt.ProjektAI.entities.User;
#Repository
public interface UserRepository extends JpaRepository < User, Long > {
User findByEmail(String email);
}
security package:
package Projekt.ProjektAI.security;
import Projekt.ProjektAI.entities.User;
import Projekt.ProjektAI.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import Projekt.ProjektAI.service.UserService;
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserService userService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/new", "/edit/{id}", "/save", "/delete/{id}")
.access("hasAnyRole('Admin')")
.and()
.authorizeRequests()
.antMatchers("/registration**","/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout")
.permitAll();
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
auth.setUserDetailsService(userService);
auth.setPasswordEncoder(passwordEncoder());
return auth;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
}
service package:
Book Service:
package Projekt.ProjektAI.service;
import Projekt.ProjektAI.entities.Book;
import Projekt.ProjektAI.repositories.BookRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class BookService {
private BookRepository repo;
#Autowired
public BookService(BookRepository repo)
{
this.repo =repo;
}
public List<Book> listAll() {
return repo.findAll();
}
public void save(Book book) {
repo.save(book);
}
public Book get(long id) {
return repo.findById(id).get();
}
public void delete(long id) {
repo.deleteById(id);
}
}
User Service interface:
package Projekt.ProjektAI.service;
import Projekt.ProjektAI.registrationDTO.UserRegistrationDTO;
import Projekt.ProjektAI.entities.User;
import org.springframework.security.core.userdetails.UserDetailsService;
public interface UserService extends UserDetailsService {
User findByEmail(String email);
User save(UserRegistrationDTO registration);
}
User Service Implementation:
package Projekt.ProjektAI.service;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
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.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import Projekt.ProjektAI.service.UserService;
import Projekt.ProjektAI.registrationDTO.UserRegistrationDTO;
import Projekt.ProjektAI.entities.User;
import Projekt.ProjektAI.entities.Role;
import Projekt.ProjektAI.service.UserService;
import Projekt.ProjektAI.registrationDTO.UserRegistrationDTO;
import Projekt.ProjektAI.repositories.UserRepository;
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserRepository userRepository;
#Autowired
private BCryptPasswordEncoder passwordEncoder;
public User findByEmail(String email) {
return userRepository.findByEmail(email);
}
public User save(UserRegistrationDTO registration) {
User user = new User();
user.setFirstName(registration.getFirstName());
user.setLastName(registration.getLastName());
user.setEmail(registration.getEmail());
user.setPassword(passwordEncoder.encode(registration.getPassword()));
user.setRoles(Arrays.asList(new Role("ROLE_USER")));
return userRepository.save(user);
}
#Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userRepository.findByEmail(email);
if (user == null) {
throw new UsernameNotFoundException("Invalid username or password.");
}
return new org.springframework.security.core.userdetails.User(user.getEmail(),
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());
}
}
application properties:
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.datasource.url=jdbc:mysql://localhost:3366/projektai?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=admin
Thank you very much for any tips!
I have searched many pages but didnt found the answer so i paste the whole code.I am testing the testclass and getting the error like "Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract org.home.mysystem.entity.User org.home.mysystem.repository.UserRepository.findOne(java.lang.String)! No property findOne found for type User!". Please someone help me
Role.java
package org.home.mysystem.entity;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
#Entity
public class Role {
#Id
private String name;
#ManyToMany(mappedBy = "roles")
private List<User> users;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public Role(String name, List<User> users) {
this.name = name;
this.users = users;
}
public Role() {
}
public Role(String name) {
this.name = name;
}
}
Task.java
package org.home.mysystem.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import org.hibernate.validator.constraints.NotEmpty;
#Entity
public class Task {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotEmpty
private String date;
#NotEmpty
private String startTime;
#NotEmpty
private String stopTime;
#NotEmpty
#Column(length=1000)
private String description;
#ManyToOne
#JoinColumn(name="USER_EMAIL")
private User user;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getStopTime() {
return stopTime;
}
public void setStopTime(String stopTime) {
this.stopTime = stopTime;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Task(String date, String startTime, String stopTime, String description, User user) {
this.date = date;
this.startTime = startTime;
this.stopTime = stopTime;
this.description = description;
this.user = user;
}
public Task(String date, String startTime, String stopTime, String description) {
this.date = date;
this.startTime = startTime;
this.stopTime = stopTime;
this.description = description;
}
public Task() {
}
}
User.java
package org.home.mysystem.entity;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
#Entity
public class User {
#Id
#Email
#NotEmpty
#Column(unique = true)
private String email;
#NotEmpty
private String name;
#Size(min = 4)
private String password;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Task> tasks;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "USER_ROLES", joinColumns={
#JoinColumn(name = "USER_EMAIL", referencedColumnName = "email") }, inverseJoinColumns = {
#JoinColumn(name = "ROLE_NAME", referencedColumnName = "name") })
private List<Role> roles;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<Task> gettasks() {
return tasks;
}
public void settasks(List<Task> tasks) {
this.tasks = tasks;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public User(String email, String name, String password) {
this.email = email;
this.name = name;
this.password = password;
}
public User() {
}
}
RoleRepository.java
package org.home.mysystem.repository;
import org.home.mysystem.entity.Role;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RoleRepository extends JpaRepository<Role, String> {
}
TaskRepository.java
public interface TaskRepository extends JpaRepository<Task, Long> {
List<Task> findByUser(User user);
}
UserRepository.java
package org.home.mysystem.repository;
import org.home.mysystem.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User,String> {
User findOne(final String email);
}
TaskService.java
package org.home.mysystem.service;
import java.util.ArrayList;
import java.util.List;
import org.home.mysystem.entity.Role;
import org.home.mysystem.entity.Task;
import org.home.mysystem.entity.User;
import org.home.mysystem.repository.TaskRepository;
import org.home.mysystem.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
#Service
public class TaskService {
#Autowired
private TaskRepository taskRepository;
public void addTask(Task task, User user) {
task.setUser(user);
taskRepository.save(task);
}
public List<Task> findUserTask(User user){
return taskRepository.findByUser(user);
}
}
UserService.java
import java.util.ArrayList;
import java.util.List;
import org.home.mysystem.entity.Role;
import org.home.mysystem.entity.User;
import org.home.mysystem.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
#Service
public class UserService {
#Autowired
private UserRepository userRepository;
public void createUser(User user) {
BCryptPasswordEncoder encoder=new BCryptPasswordEncoder();
user.setPassword(encoder.encode(user.getPassword()));
Role userRole=new Role("USER");
List<Role> roles=new ArrayList<>();
roles.add(userRole);
user.setRoles(roles);
userRepository.save(user);
}
public void createAdmin(User user) {
BCryptPasswordEncoder encoder=new BCryptPasswordEncoder();
user.setPassword(encoder.encode(user.getPassword()));
Role userRole=new Role("ADMIN");
List<Role> roles=new ArrayList<>();
roles.add(userRole);
user.setRoles(roles);
userRepository.save(user);
}
public User findOne(String email) {
return userRepository.findOne(email);
}
}
MyApplicationTest.java
package org.home.mysystem;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.List;
import org.home.mysystem.entity.Task;
import org.home.mysystem.entity.User;
import org.home.mysystem.service.TaskService;
import org.home.mysystem.service.UserService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest
public class MySystemApplicationTests {
#Autowired
private UserService userService;
#Autowired
private TaskService taskService;
#Before
public void initDb() {
{
User newUser = new User("testUser#mail.com", "testUser", "123456");
userService.createUser(newUser);
}
{
User newUser = new User("testAdmin#mail.com", "testAdmin", "123456");
userService.createUser(newUser);
}
Task userTask = new Task("03/01/2018", "00:11", "11:00", "You need to work today");
User user = userService.findOne("testUser#mail.com");
taskService.addTask(userTask, user);
}
#Test
public void testUser() {
User user=userService.findOne("testUser#mail.com");
assertNotNull(user);
User admin=userService.findOne("testAdmin#mail.com");
assertEquals(admin.getEmail(),"testAdmin#mail.com");
}
#Test
public void testTask() {
User user=userService.findOne("testUser#mail.com");
List<Task> task=taskService.findUserTask(user);
assertNotNull(task);
}
}
The issue is that Spring is expecting something else as you are giving it.
findOne is by default defined to take an ID (primary key) to load the entity by. So it expects a long or Long (as far as I know). It takes the name of the parameter given (email) and is searching for an ID with that name and that simply doesn't add up.
If you want to search by an email or other field that has been defined by you, you need to use the following syntax:
Example 1
Example field to search by: email
Method in repository:
User findByEmail(String email)
Example 2
Example field to search by: username
Method in repository:
User findByUsername(String username)
I hope this helps!
I changed my code according to R4J answer.
I think there's something more to correct since I can't display anything now...
result I get - console is clear (no errors)
Could anyone be so kind and help me find the issue?
Below I describe my project:
DB:
database table "users"
TestUser.java
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(name = "USERS")
public class TestUser {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name = "email", nullable = false)
private String email;
#Column(name = "password", nullable = false)
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
TestService.class
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.test.testapp.dao.UserDao;
import com.test.testapp.model.TestUser;
#Component
public class TestService {
#Autowired
UserDao userDao;
public List<TestUser> getUsers() {
return userDao.findAll();
}
}
UserDao.class
import java.util.List;
import javax.persistence.PersistenceException;
import com.test.testapp.model.TestUser;
public interface UserDao /* extends CrudRepository<TestUser, Integer>*/{
public List<TestUser> findAll() throws PersistenceException;
}
UserDaoImpl.java
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import org.jvnet.hk2.annotations.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.test.testapp.dao.UserDao;
import com.test.testapp.model.TestUser;
#Repository("userDao")
#Service
public class UserDaoImpl implements UserDao {
#Autowired
private EntityManager entityManager;
#PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public TestUser findPersonById(Integer id) {
return entityManager.find(TestUser.class, id);
}
#Override
#Transactional
public List<TestUser> findAll() {
try {
return entityManager.createQuery("SELECT u FROM Users u ORDER BY p.id", TestUser.class).getResultList();
} finally {
entityManager.close();
}
}
}
TestWebApi.java
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Controller
#Path("test")
public interface TestWebApi {
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/")
public Response getUsers();
}
TestWebApiImpl.java
import java.util.List;
import javax.inject.Inject;
import javax.ws.rs.core.Response;
import com.test.testapp.model.TestUser;
import com.test.testapp.service.TestService;
import com.test.testapp.web.TestWebApi;
public class TestWebApiImpl implements TestWebApi {
#Inject
TestService testService;
#Override
public Response getUsers() {
List<TestUser> test = testService.getUsers();
return Response.ok().entity(test).build();
}
}
You are mixing JAX-RS annotations with Spring-MVC annotations. If you want to stick to JAX-RS then your code should look like this:
#Path("users")
#Component
public class UserController {
#Inject
UserService userService;
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/")
public List<User> getUsers() {
return userService.findAll();
}
#GET
#Path("/users/{name}")
#Produces(MediaType.APPLICATION_JSON)
public Response getUserByName(#NotNull #PathParam("name") String username) {
User user = userService.findByName(username);
return Response.ok().entity(user).build();
}
}
Currently, you have #RestController on your Class which makes it a Spring Rest Controller. So Spring scans all methods and finds '#RequestMapping("/user/{name}")' and '#RequestMapping("/users")' so it binds these methods to default GET operations and ignores completely #PathVariable annotation because it comes from JAX-RS not Spring.
Spring-MVC version of your code would be:
#RestController
#RequestMapping("/")
public class UserController {
#Inject
UserService userService;
#RequestMapping(value = "/users", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public List<User> getUsers() {
return userService.findAll();
}
#RequestMapping(value = "/users/{name}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public Response getUserByName(#NotNull #PathVariable("name") String username) {
User user = userService.findByName(username);
return Response.ok().entity(user).build();
}
}