@Secured и @RolesAllowed в Spring Security не работает с ENUM
Пишу свой первый боевой проект на Spring MVC. Есть класс User, от которого наследуются по связям три класса Customer, Admin, Cook. Соответственно, созданы и таблицы. Добавил в проект Spring Security и систему авторизации. Вход в систему происходит отлично, после чего меня перенаправляет на Swagger страницу. Но ни один метод мне не доступен. Я понимаю, что все проблемы от ENUM ROLE, который я использую. Подскажите пожалуйста, как можно это исправить, сохранив при этом ENUM.
User:
@ApiModel
@Data
@Entity
@Table(name = "pg_user", schema = "public")
public class User implements UserDetails {
public User() { // Пустой конструктор для Hibernate
}
// Поля
private @Id
@GeneratedValue
Long id;
@Column(name = "login")
private String login;
@Size(min = 5, max = 30)
@Column(name = "password")
private String password;
@Enumerated(EnumType.STRING)
@Column(name = "role")
private Role role;
@Column(name = "name")
private String name;
@Column(name = "last_name")
private String lastName;
// Методы
//
// GrantedAuthority
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role));
}
// userName == login (одно и тоже)
@Override
public String getUsername() {
return login;
}
// Во всех флагах стоит TRUE, так как не используются
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
//
}
Role:
public enum Role {
COOK, ADMIN, CUSTOMER
// Fields
// Constructor
}
Для примера Customer:
@Data
@Entity
@Table(name = "customer", schema = "public")
public class Customer {
public Customer() { // Пустой конструктор для Hibernate
}
// Поля
// name, lastName, login, password берем от класса User через связи;
private @Id
@GeneratedValue
Long id;
@Column(name = "wallet")
private double wallet;
//Relationships
//
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "user_id", referencedColumnName = "id") // Join without Customer in User class
@NotFound(action = NotFoundAction.IGNORE)
private User user;
//Лист заказов
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL)
@JsonIgnore // Таким образом я предотвратил рекурсию
private List<Order> orderList;
}
Так же Spring Security:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// Поля
//
private UserService userService;
private PasswordEncoder passwordEncoder;
// Injects in SETTERS
//
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
@Autowired
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
// Methods
//
// Тут мы переопределяем метод конфигураций
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.antMatchers("/admin/**").hasRole(String.valueOf(Role.ADMIN))
.antMatchers("/customer/**").hasRole(String.valueOf(Role.CUSTOMER))
.antMatchers("/cook/**").hasRole(String.valueOf(Role.COOK))
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
// Тут мы переопределяем для работы с внешней БД
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder);
}
// Beans
//
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userService);
authenticationProvider.setPasswordEncoder(passwordEncoder);
return authenticationProvider;
}
@Bean
public static PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder(8);
}
// Возвращаем сервис пользовател для userDetServ
@Bean
public UserDetailsService userDetailsService() {
return userService;
}
}
CustomerController:
@Api(value = "Работа с Заказчиком", tags = {"Заказчик"})
@RestController
@RequestMapping("/customer")
@Secured("CUSTOMER")
public class CustomerController {
//Constructor
//
// Injects через конструктор
@Autowired
public CustomerController(CustomerRepository customerRepository, CustomerService customerService, UserService userService) {
this.customerRepository = customerRepository;
this.customerService = customerService;
this.userService = userService;
}
// Fields
// Injects into constructor
//
private final CustomerRepository customerRepository;
private final CustomerService customerService;
private final UserService userService;
// GET MAPPING
//
// POST MAPPING
//
// Сделать заказ
@PostMapping("/make/order")
public void makeOrder(String address, String phoneNumber, Long customerId,
Long cookId, @RequestParam List<Long> dishList, Date date) {
customerService.makeOrder(address, phoneNumber, customerId, cookId, dishList, date);
}
// Регистрация
@PostMapping("/registration")
public void registration(User user, String login, String password, String name, String lastName){
customerService.registration(user, login, password, name, lastName);
}
// Оставить отзыв
@PostMapping("/set/review")
public void setReview(String text, int rate, Long id) {
customerService.setReview(text, rate, id);
}
// PUT MAPPING
//
// Заказчик может редактировать свою карточку (поиск по ID)
@PutMapping("/edit/{id}")
Customer editCustomer(@PathVariable Long id, User user, @RequestParam double wallet) {
return customerService.editCustomer(id, user, wallet);
}
// Снять деньги со своего депозита (Заказчик)
@PutMapping("/{id}/withdraw/{money}")
void withdrawMoney(@PathVariable Long id, @RequestParam double money) {
customerService.withdrawMoney(id, money);
}
// Изменить свой пароль
@PutMapping("/change/password")
void changePassword(@RequestParam String login, @RequestParam String newPass) {
userService.changePassword(login, newPass);
}
// Внести деньги на счет (Заказчик)
@PutMapping("/{id}/deposit/money")
public void depositMoney(@PathVariable Long id, @RequestParam double money) {
customerService.depositMoney(id, money);
}
// Отменить Заказ
@PutMapping("/cancel/order/{id}")
public void cancelOrder(@PathVariable Long id){
customerService.cancelOrder(id);
}
// DELETE MAPPING
//
}
P.S Пробовал как и @Secured так же @RolesAllowed.
{
"timestamp": "2020-05-08T12:30:05.896+0000",
"status": 403,
"error": "Forbidden",
"message": "Forbidden",
"path": "/cook/change/password"
}
