I've been trying to create a spring security logic to authorize users (inserted into my database) to do different things based on their roles (simple). I'm supposed to have ROLE_USER and ROLE_ADMIN, but I don't think any of them work. Please help. I'll try to put every bit of important code here (even the imports).
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.security.core.GrantedAuthority;
import com.vitoria.enums.RoleName;
@Entity
@Table(name = "TB_ROLE")
public class RoleModel implements GrantedAuthority, Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID roleId;
@Enumerated(EnumType.STRING)
@Column(nullable = false, unique = true)
private RoleName roleName;
@Override
public String getAuthority() {
return this.roleName.toString();
}
public UUID getRoleId() {
return roleId;
}
public void setRoleId(UUID roleId) {
this.roleId = roleId;
}
public RoleName getRoleName() {
return roleName;
}
public void setRoleName(RoleName roleName) {
this.roleName = roleName;
}
}
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
@Entity
@Table(name = "TB_USER")
public class UserModel implements UserDetails, Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID userId;
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false)
private String password;
@ManyToMany
@JoinTable(name = "TB_USERS_ROLES",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private List<RoleModel> roles;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.roles;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public String getUsername() {
return this.username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
}
public enum RoleName {
ROLE_ADMIN,
ROLE_USER;
}
import javax.transaction.Transactional;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.vitoria.models.UserModel;
import com.vitoria.repositories.UserRepository;
@Service
@Transactional
public class UserDetailsServiceImpl implements UserDetailsService {
final UserRepository userRepository;
public UserDetailsServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserModel userModel = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username));
return new User(userModel.getUsername(), userModel.getPassword(), true, true, true,true, userModel.getAuthorities());
}
}
import org.springframework.data.jpa.repository.JpaRepository;
import com.vitoria.models.RoleModel;
public interface RoleRepository extends JpaRepository<RoleModel, Long> {
RoleModel findByRoleName(String roleName);
}
import java.util.Optional;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.vitoria.models.UserModel;
@Repository
public interface UserRepository extends JpaRepository<UserModel, UUID> {
Optional<UserModel> findByUsername(String username);
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeHttpRequests()
.anyRequest().authenticated()
.and()
.csrf().disable();
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.vitoria.models.Flowers;
import com.vitoria.repositories.FlowersRepository;
@RestController
@CrossOrigin(origins = "*", maxAge = 3600)
@EnableAutoConfiguration
@RequestMapping("/flowers")
public class FlowersController {
@Autowired
private FlowersRepository repo;
@PreAuthorize("hasRole('ROLE_USER')")
@GetMapping
public ResponseEntity<List<Flowers>> findAll(){
List<Flowers> allFlowers=repo.findAll();
return ResponseEntity.ok().body(allFlowers);
}
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
@PostMapping("/insert")
public ResponseEntity<Flowers> insert(@RequestBody Flowers flower){
Flowers entity=flower;
repo.save(entity);
return ResponseEntity.ok().body(entity);
}
@PreAuthorize("hasRole('ROLE_ADMIN')")
@DeleteMapping("/delete/{id}")
public ResponseEntity<Void> deleteById(@PathVariable Integer id){
repo.deleteById(id);
return ResponseEntity.noContent().build();
}
}
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.vitoria.models.UserModel;
import com.vitoria.repositories.UserRepository;
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserRepository repo;
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
@GetMapping
public ResponseEntity<List<UserModel>> findAll(){
List<UserModel> users=repo.findAll();
return ResponseEntity.ok().body(users);
}
@PreAuthorize("hasRole('ROLE_USER')")
@GetMapping("/{username}")
public ResponseEntity<Optional<UserModel>> findByUsername(@RequestParam("username")String username){
Optional<UserModel> user=repo.findByUsername(username);
return ResponseEntity.ok().body(user);
}
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/save")
public ResponseEntity<UserModel> insert(@RequestBody UserModel user){
UserModel entity=user;
user.setPassword(passwordEncoder().encode(user.getPassword()));
repo.save(entity);
return ResponseEntity.ok().body(entity);
}
private PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
my database looks like this:
I think this is all. Please keep in mind that when I try to make ->any<- request to any endpoint it comesback unauthorized. SO, I tried something else: taking off the role permission (using the @PreAuthorize("permitAll()")) of get all users and I still get 401 as return! Please please help me.