Vaadin BeanCreationException: during trying to call save method of my service class - spring-boot

Hi I have a little Vaadin project. In there, I've a UserUtils.class which has a createNewUser method which looks like this:
LoginView:
import com.vaadin.flow.component.html.H1;
import com.vaadin.flow.component.login.LoginForm;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.util.Collections;
import static com.packagename.utils.UserUtils.createNewUser;
#Route("login")
#PageTitle("Login - packagename")
public class LoginView extends VerticalLayout implements BeforeEnterObserver {
private LoginForm login = new LoginForm();
private PasswordEncoder passwordEncoder;
public LoginView(){
createNewUser("daniel.tran", "cAWFCMaa22", true, "ADMIN");
addClassName("login-view");
setSizeFull();
setAlignItems(Alignment.CENTER);
setJustifyContentMode(JustifyContentMode.CENTER);
login.setAction("login");
add(
new H1("Willkommen!"),
login
);
}
#Override
public void beforeEnter(BeforeEnterEvent event) {
// Inform the user about an authentication error
if (!event.getLocation()
.getQueryParameters()
.getParameters()
.getOrDefault("error", Collections.emptyList())
.isEmpty()) {
login.setError(true);
}
}
}
UserUtils.class:
import com.packagename.backend.entity.UserEntity;
import com.packagename.backend.service.UserService;
import com.packagename.security.SecurityConfiguration;
import com.packagename.ui.views.login.LoginView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
public class UserUtils {
#Autowired
private LoginView loginView;
private static UserService userService;
private PasswordEncoder passwordEncoder;
public static void createNewUser(String pUsername, String pPassword, boolean pStatus, String pRole) {
if (!UserUtils.userExists(pUsername)) {
userService = new UserService();
PasswordEncoder passwordEncoder = SecurityConfiguration.passwordEncoder();
String encodedPassword = passwordEncoder.encode(pPassword);
UserEntity user = new UserEntity();
user.setUserName(pUsername);
user.setPassword(encodedPassword);
user.setStatus(pStatus);
user.setRoles(pRole);
userService.save(user);
}
}
private static boolean userExists(String pUsername) {
userService = new UserService();
UserEntity user = new UserEntity();
user.setUserName(pUsername);
boolean exists = userService.exists(user);
return exists;
}
}
UserService.class:
import com.packagename.backend.entity.UserEntity;
import com.packagename.backend.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
#Service
public class UserService {
private UserRepository userRepository;
private Logger LOGGER;
#Autowired
public UserService(UserRepository pUserRepository) {
this.userRepository = pUserRepository;
}
public UserService() {}
public List<UserEntity> findAll() {
return userRepository.findAll();
}
public long count() {
return userRepository.count();
}
public void delete(UserEntity user) {
userRepository.delete(user);
}
public void save(UserEntity user) {
if (user == null) {
LOGGER.log(Level.SEVERE, "Contact is null. Are you sure you have connected your form to the application?");
return;
}
userRepository.save(user);
}
public boolean exists(UserEntity user) {
Example<UserEntity> example = Example.of(user);
boolean exists = userRepository.exists(example);
return exists;
}
}
UserEntity.class:
import javax.persistence.*;
#Entity
#Table(name = "PSYS_USERS")
public class UserEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int userid;
private String userName;
private String password;
private boolean status;
private String roles;
public UserEntity(){}
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 String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getRoles() {
return roles;
}
public void setRoles(String roles) {
this.roles = roles;
}
}
UserRepository.class
import com.packagename.backend.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface UserRepository extends JpaRepository<UserEntity, Integer> {
Optional<UserEntity> findByUserName(String userName);
}
And always when it comes to the situtation, trying to call the userService methods, then it throws the following exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.packagename.ui.views.login.LoginView': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.packagename.ui.views.login.LoginView]: Constructor threw exception; nested exception is java.lang.NullPointerException
I tried to create a default constructor, at the entity and also at the service class but nothing want help.
So far,
Daniel

new UserService(); - this is the problem.
you cannot instantiate spring components on your own, you have to let spring inject/autowire them.
Places where you can inject Spring components are spring components themselves, and with Vaadin, you can inject in your views that have a #Route annotation. LoginView is such a view. So there you inject the UserService, and pass it along to the createNewUser method.
// LoginView constructor
// userService is injected/autowired this way
public LoginView(UserService userService){
createNewUser("daniel.tran", "cAWFCMaa22", true, "ADMIN", userService);
addClassName("login-view");
setSizeFull();
setAlignItems(Alignment.CENTER);
setJustifyContentMode(JustifyContentMode.CENTER);
login.setAction("login");
add(
new H1("Willkommen!"),
login
);
}
// UserUtils
public static void createNewUser(String pUsername, String pPassword, boolean pStatus, String pRole, UserService userService) {
if (!UserUtils.userExists(pUsername, userService)) {
PasswordEncoder passwordEncoder = SecurityConfiguration.passwordEncoder();
String encodedPassword = passwordEncoder.encode(pPassword);
UserEntity user = new UserEntity();
user.setUserName(pUsername);
user.setPassword(encodedPassword);
user.setStatus(pStatus);
user.setRoles(pRole);
userService.save(user);
}
}
private static boolean userExists(String pUsername, UserService userService) {
UserEntity user = new UserEntity();
user.setUserName(pUsername);
boolean exists = userService.exists(user);
return exists;
}
By the way, UserUtils is not a Spring Component so you cant autowire the loginView there either - good thing it's not used anyway

Related

Spring Security 403 even with correct username and password , i can't authenticate

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.

when I post ,it shows error of 404 not found in spring boot even when I have declared #RequestMapping

I have made a userservice where I want to add new user, find user by id and also by other attributes. I have extended JPA repository since I learned that there is already functions. But I can't even save a new user.
This is my model
package bt.gov.dit.userservice.model;
import javax.persistence.*;
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private Long Id;
#Column
private String name;
#Column
private String email;
#Column
private String role;
public Long getId() {
return Id;
}
public void setId(Long id) {
Id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public User(Long id, String name, String email, String role) {
Id = id;
this.name = name;
this.email = email;
this.role = role;
}
public User() {
}
}
This is my repository
package bt.gov.dit.userservice.dao;
import bt.gov.dit.userservice.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface UserRepository extends JpaRepository<User,Long> {
User findUserByRole(String role);
}
This is my service
package bt.gov.dit.userservice.service;
import bt.gov.dit.userservice.dao.UserRepository;
import bt.gov.dit.userservice.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class UserService {
#Autowired
private UserRepository userRepository;
public User save(User user){
return userRepository.save(user);
}
public User getByRole(String role){
return userRepository.findUserByRole(role);
}
}
And this is my Controller
package bt.gov.dit.userservice.controller;
import bt.gov.dit.userservice.model.User;
//import bt.gov.dit.userservice.service.UserService;
import bt.gov.dit.userservice.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
#RestController
#RequestMapping("/api")
public class UserController {
#Autowired
private UserService userService;
#PostMapping
public ResponseEntity<User> create(#Valid #RequestBody User user) {
User updated = userService.create(user);
return new ResponseEntity<User>(updated, new HttpHeaders(), HttpStatus.OK);
}
#GetMapping("/{role_id}")
public ResponseEntity<User> getUserByRole(#PathVariable("role_id") String role)
{
User entity = userService.getByRole(role);
return new ResponseEntity<User>(entity, new HttpHeaders(), HttpStatus.OK);
}
}
I have just started learning Spring boot and I can't seem to understand what is wrong in code. I want to insert/save new user. But when I call /api/user it says 404 not found. I am using h2 in-memory db.
I think the issue is the controller method argument name - role->role_id
#GetMapping("/{role_id}")
public ResponseEntity<User> getUserByRole(#PathVariable("role_id") String role_id)
{
User entity = userService.getByRole(role_id);
return new ResponseEntity<User>(entity, new HttpHeaders(), HttpStatus.OK);
}
the role_id should be same as you mentioned in the routes.
Route example->localhost:8080/api/2
you need to map the other part of the request like this:
#PostMapping(value="/user", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE )
I also recommend you to use Springfox Swagger UI using the annotation #EnableSwagger2
This will provide you an user interface with all requests at http://localhost:8080/swagger-ui.html
Link:
https://www.baeldung.com/swagger-2-documentation-for-spring-rest-api

How do I use Bcrypt in my spring boot application to secure passwords?

My username and password is coming from angular to spring boot which stores it in mysql. I have simple model, repository, services and controller packages. My model is registration which has name username and password and while loggin in, the username and password is fetched from the registration table
My Registration Model Class
package com.example.angular.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="registration")
public class Registration {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private int id;
private String name;
private String username;
private String password;
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public Registration(String name, String username, String password) {
super();
this.name = name;
this.username = username;
this.password = password;
}
public Registration() {
super();
// TODO Auto-generated constructor stub
}
#Override
public String toString() {
return "Registration [id=" + id + ", name=" + name + ", username=" + username + ", password=" + password + "]";
}
}
My registration controller
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.CrossOrigin;
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.example.angular.model.Registration;
import com.example.angular.service.RegistrationService;
#RestController
#CrossOrigin(origins="*", allowedHeaders = "*")
#RequestMapping("/register")
public class RegistrationController {
#Autowired
private RegistrationService res;
#PostMapping("/registeruser")
public ResponseEntity<Registration> registeruser(#RequestBody Registration reg)
{
Registration resk= res.registeruser(reg);
return new ResponseEntity<Registration>(resk,HttpStatus.OK);
}
#PostMapping("/login")
public ResponseEntity<Registration> loginuser(#RequestBody Registration reg)
{
List<Registration> regList = res.getusername(reg.getUsername(), reg.getPassword());
System.out.println("Logged in! ");
//return new ResponseEntity<Registration>(reg.getUsername(), HttpStatus.OK);
return null;
}
}
do I have to add any configuartion file in a package or do I have to use bcrypt in angular? Youtube videos are confusing please help
I think you want Spring Security. In this case you should use BCryptPasswordEncoder. Simply create Bean for encryption.
private static final String ADMIN = "ADMIN";
private static final String USER = "USER";
#Autowired
private UserDetailService userDetailService;
#Autowired
private DataSource dataSource;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).dataSource(dataSource)
.passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/admin").hasRole(ADMIN)
.antMatchers("/user").hasAnyRole(ADMIN, USER)
.antMatchers("/", "/register-user").permitAll()
.and().formLogin();
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
If you just want to encrypt the password in BCrypt. You can use like this
String password = "password";
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String hashedPassword = passwordEncoder.encode(password);

Roles not working properly in Spring security [duplicate]

This question already has answers here:
Springboot Security hasRole not working
(3 answers)
Closed 3 years ago.
I am working on a spring security based web application in which I want to limit the items on the side bar based upon whether the logged in user has role ADMIN or USER. As far as authentication is concerned, everything is working fine but roles are not working as expected.
Following this post
For example -
<security:authorize access="hasRole('ADMIN')">
<li class=" nav-item"><a href="<c:url value = "/mapview/list"/>"><i
class="fa fa-map-marker"></i><span class="menu-title" data-i18n="">MapView</span></a>
</li>
</security:authorize>
The above element never gets visible even though I log in as - ADMIN.
Can someone please help me here in understanding what is going wrong.
Security Config
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
#Bean
public AuthenticationProvider authProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
provider.setPasswordEncoder(new BCryptPasswordEncoder());
return provider;
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests().antMatchers("/login", "/resource/**").permitAll()
.anyRequest().fullyAuthenticated()
.and()
.formLogin()
.loginPage("/login").usernameParameter("username").passwordParameter("password").permitAll()
.loginProcessingUrl("/doLogin").successForwardUrl("/postLogin").failureUrl("/loginFailed").and()
.logout().logoutUrl("/doLogout").logoutSuccessUrl("/logout").permitAll().and().csrf().disable();
}
}
UserDetailsImpl
public class UserDetailsImpl implements UserDetails {
private static final long serialVersionUID = 1L;
private Collection<SimpleGrantedAuthority> authorities;
private String username;
private String password;
private Boolean enabled = true;
public void setAuthorities(Collection<SimpleGrantedAuthority> authorities) {
this.authorities = authorities;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
#Override
public String getPassword() {
return password;
}
#Override
public String getUsername() {
return username;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return enabled;
}
UserDetailsService
#Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private UserService userService;
private Converter<User, UserDetails> userUserDetailsConverter;
#Autowired
#Qualifier(value = "userToUserDetails")
public void setUserUserDetailsConverter(Converter<User, UserDetails> userUserDetailsConverter) {
this.userUserDetailsConverter = userUserDetailsConverter;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return userUserDetailsConverter.convert(userService.findByUserName(username));
}
}
UserToUserDetails
#Component
public class UserToUserDetails implements Converter<User, UserDetails>{
#Override
public UserDetails convert(User user) {
UserDetailsImpl userDetails = new UserDetailsImpl();
if (user != null) {
userDetails.setUsername(user.getUsername());
userDetails.setPassword(user.getEncryptedPassword());
userDetails.setEnabled(user.getEnabled());
Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
user.getRoles().forEach(role -> {
authorities.add(new SimpleGrantedAuthority(role.getName()));
});
userDetails.setAuthorities(authorities);
}
return userDetails;
}
}
Controller
#SessionAttributes({ "currentUser" })
#Controller
public class HomeController {
//skipping other mappings
#RequestMapping(value = "/postLogin", method = RequestMethod.POST)
public String postLogin(Model model, HttpSession session) {
UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder
.getContext().getAuthentication();
validatePrinciple(authentication.getPrincipal());
String username = ((UserDetailsImpl) authentication.getPrincipal()).getUsername();
model.addAttribute("currentUser", username);
return "redirect:/dashboard";
}
}
User
#Entity
public class User extends Auditable<String> {
//skipping other details
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "user_role",
joinColumns = { #JoinColumn(name = "user_id") },
inverseJoinColumns = { #JoinColumn(name = "role_id") })
private Set<Role> roles = new HashSet<>();
}
Tables created in db-
user
role
user_role
EDIT 1
Just added this mapping inside my controller and Once I login, if i hit /test on browser, both the booleans show false. I have no idea why the roles are not being set.. :-(
#GetMapping(value = "/test")
public void test(SecurityContextHolderAwareRequestWrapper request) {
boolean b = request.isUserInRole("ADMIN");
System.out.println("ROLE_ADMIN=" + b);
boolean c = request.isUserInRole("USER");
System.out.println("ROLE_USER=" + c);
}
EDIT 2
But, at the same time, below code shows role as ADMIN
public void test(SecurityContextHolderAwareRequestWrapper request) {
for (GrantedAuthority authority : SecurityContextHolder.getContext().getAuthentication().getAuthorities()) {
String userRole = authority.getAuthority();
System.out.println(userRole);
}
}
This looks like information is getting lost somewhere between retrieval from database and returning a response to the browser (obviously). Good thing you have a debugger, so I would start by tracing each step from where you access your database data, until you return that information. Follow every single step until you find where is it being lost, and post back when you have narrowed it down to a single place. If not maybe we can start looking at your html/script/template engine, but only after we are sure info is reaching browser.

Authentication failed (Bad Credentuals) in Spring Security with hibernate for REST

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);

Resources