有一个Spring-MVC
项目,其中有三种类型的用户:Customer
,Admin
,Cook
。它们全部都从类User
继承。只需使用静态字符串常量(显示在ENUM
类中),就无需使用User
创建角色。添加Spring Security
后,授权成功,但是当我尝试执行其中一个类(Customer,Admin或Cook)的方法时,它给出了 json错误403 :
{
"timestamp": "2020-05-08T19:48:43.999+0000",
"status": 403,
"error": "Forbidden",
"message": "Forbidden",
"path": "/admin/cooks"
}
请告诉我我做错了什么。错误在哪里。
用户:
package com.tinychiefdelights.model;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.*;
import javax.validation.constraints.Size;
import java.util.Collection;
import java.util.Collections;
@ApiModel
@Data
@Entity
@Table(name = "pg_user", schema = "public")
public class User implements UserDetails {
// Roles
//
public static final String ROLE_ADMIN = "ADMIN";
public static final String ROLE_CUSTOMER = "CUSTOMER";
public static final String ROLE_COOK = "COOK";
//
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;
@Column(name = "role")
private String 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;
}
//
}
例如,我仅添加一个Admin类:
管理员:
package com.tinychiefdelights.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.persistence.*;
@ApiModel
@Data
@Entity
@Table(name = "pg_user", schema = "public")
public class Admin {
public Admin() { // Пустой конструктор для Hibernate
}
// Поля
// name, lastName, login, password берем от класса User через связи;
@ApiModelProperty
private @Id
@GeneratedValue
Long id;
// Relationships
//
@ApiModelProperty
@OneToOne
@JoinColumn(name = "id") // Join without Admin in User class
private User user;
}
AdminService:
@Service
public class AdminService extends UserService {
// Поля
//
// Injects in setters
private AdminRepository adminRepository; // Администратор
private OrderRepository orderRepository; // Заказ
private CookRepository cookRepository; // Повар
private CustomerRepository customerRepository; // Заказчик
// Getters and Setters
//
// Делаем inject через сеттеры
@Autowired
public void setAdminRepository(AdminRepository adminRepository) {
this.adminRepository = adminRepository;
}
@Autowired
public void setOrderRepository(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
@Autowired
public void setCookRepository(CookRepository cookRepository) {
this.cookRepository = cookRepository;
}
@Autowired
public void setCustomerRepository(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
}
// Методы
//
// Вывод списка всех заказов
public List<Order> getAllOrders() {
return orderRepository.findAll();
}
// Вывод информации по конкретному заказу
public Order getOrderInfo(Long id) {
try {
return orderRepository.getById(id);
} catch (NotFoundException e) {
throw new NotFoundException(id);
}
}
// Вывод Повара по ID
public Cook getCook(Long id) {
try {
return cookRepository.getByIdAndUserRole(id, "COOK");
} catch (NotFoundException e) {
throw new NotFoundException(id);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException();
}
}
// Изменить карту повара
public void editCook(Long id, User user, float rating, String aboutCook) {
Cook cook = cookRepository.getByIdAndUserRole(id, "COOK");
try {
cook.setUser(user);
cook.setRating(rating);
cook.setAboutCook(aboutCook);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException();
} catch (NotFoundException e) {
throw new NotFoundException(id);
}
}
// Вывод всех поваров
public List<Cook> getAllCooks() {
return cookRepository.findByUserRole("COOK");
}
// Удалить Повара
public void deleteCook(Long id) {
Cook cook = cookRepository.getByIdAndUserRole(id, "COOK");
try {
cookRepository.delete(cook);
} catch (Exception e) {
throw new NotFoundException(id);
}
}
// Вывод всех Заказчиков
public List<Customer> getAllCustomers() {
return customerRepository.findByUserRole("CUSTOMER");
}
// Вывод Заказчика по ID
public Customer getCustomer(Long id) {
try {
return customerRepository.getByIdAndUserRole(id, "CUSTOMER");
} catch (NotFoundException e) {
throw new NotFoundException(id);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException();
}
}
}
AdminController:
@Api(value = "Работа с Админом", tags = {"Администратор"})
@RestController
@RequestMapping("/admin")
@RolesAllowed("ADMIN")
public class AdminController {
// Constructor
//
// Inject через конструктор
@Autowired
public AdminController(AdminRepository adminRepository, AdminService adminService, UserService userService) {
this.adminRepository = adminRepository;
this.adminService = adminService;
this.userService = userService;
}
// Поля
// All injects into constructor
private final AdminRepository adminRepository;
private final AdminService adminService;
private final UserService userService;
// Методы
//
// GET MAPPING
//
// Вывод списка всех заказов
@GetMapping("/orders")
List<Order> getAllOrders() {
return adminService.getAllOrders();
}
// Вывод информации по конкретному заказу по ID
@GetMapping("/order/{id}")
Order getOrderInfo(@PathVariable Long id) {
return adminService.getOrderInfo(id);
}
// Вывод всех Поваров
@GetMapping("/cooks")
List<Cook> getAllCooks() {
return adminService.getAllCooks();
}
// Вывод Повара по ID
@GetMapping("/cook/{id}")
Cook getCook(@PathVariable Long id) {
return adminService.getCook(id);
}
// Вывод всех пользователей
@GetMapping("/customers")
List<Customer> getAllCustomer() {
return adminService.getAllCustomers();
}
// Вывод Заказчика по ID
@GetMapping("/customer/{id}")
Customer getCustomer(@PathVariable Long id) {
return adminService.getCustomer(id);
}
// POST MAPPING
//
// PUT MAPPING
//
// Изменяем Повара по ID
@PutMapping("/edit/cook/{id}")
void editCook(@PathVariable Long id, User user, @PathVariable float rating, String aboutCook) {
adminService.editCook(id, user, rating, aboutCook);
}
// Поменять пароль
@PutMapping("/change/password")
void changePassword(@RequestParam String login, @RequestParam String newPass) {
userService.changePassword(login, newPass);
}
// DELETE MAPPING
//
// Удалить конкретного Повара по ID
@DeleteMapping("/delete/cook/{id}")
void removeCook(@PathVariable Long id) {
adminService.deleteCook(id);
}
}
我使用注释 @RolesAllowed 。
SpringWebConfig:
@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()
.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);
}
// Возвращаем сервис пользовател для userDetService
@Bean
public UserDetailsService userDetailsService() {
return userService;
}
}
答案 0 :(得分:4)
要解决此问题,请在开始时将以下内容添加到WebSecurityConfig
方法中的configure
类中:
http
.cors().disable()
.csrf().disable()
答案 1 :(得分:0)
您应该将@RolesAllowed("ADMIN")
更改为@RolesAllowed("ROLE_ADMIN")
,以使其与角色名称的常规前缀(您在User::getAuthorities
中使用的前缀)相匹配。