#spring #spring-boot #spring-security
#spring #spring-boot #spring-безопасность
Вопрос:
Я изучаю Spring Security и пытаюсь создать простой веб-сервис, который содержит название книги. Я пытаюсь реализовать свою безопасность, чтобы каждый мог использовать GET на моей конечной точке / books / book, а авторизованные пользователи могли отправлять сообщения в / books / book. По какой-то причине моя конечная точка POST сообщает, что мой пользователь авторизован, даже если я добавил заголовок аутентификации с правильными учетными данными.
Я просматривал разные примеры в Интернете, но, похоже, я просто не могу выяснить, где была моя ошибка.
Мой UserDetailsService содержит одного пользователя с именем batman, у которого есть роль ПОЛЬЗОВАТЕЛЯ, необходимая для публикации в / books / book
@Component
public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String string) throws UsernameNotFoundException {
return User.withDefaultPasswordEncoder().username("batman").password("pass").roles("ADMIN", "USER").build();
}
}
Мой SecurityConfig должен разрешать запрос GET для неавторизованных пользователей в / book / books. Эта часть работает.
Метод POST для /book / books должен быть разрешен только для авторизованных пользователей. Эта часть не работает и возвращает несанкционированный для всех.
@EnableWebSecurity
public class CustomSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().and().cors().disable().authorizeRequests()
.antMatchers(HttpMethod.GET, "/books/book").permitAll()
.antMatchers(HttpMethod.POST, "/books/**").hasRole("ADMIN")
.and()
.httpBasic();
}
}
Мой BookController выглядит следующим образом
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
@GetMapping("/book")
public ResponseEntity<Object> getAll() {
return new ResponseEntity<>(bookService.getAll(), HttpStatus.OK);
}
@PostMapping("/book")
public ResponseEntity<Object> add(@RequestBody Book book) {
bookService.addBook(book);
return ResponseEntity.ok().build();
}
}
Мой книжный сервис
@Service
public class BookService {
@Autowired
private BookRepository bookRepository;
public Collection getAll() {
return bookRepository.findAll();
}
public void addBook(Book book) {
bookRepository.save(book);
}
public void deleteBook(Long id) {
bookRepository.deleteById(id);
}
public void updateBook(Long id, Book book){
bookRepository.findById(id).map((entry) -> {
entry.setTitle(book.getTitle());
bookRepository.save(book);
return entry;
});
}
}
Мое хранилище книг
@Repository
public interface BookRepository extends JpaRepository<Book, Long>{
List<Book> findBookByTitle(String title);
}
Мой класс Book
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Book {
@Id
@GeneratedValue
private Long id;
private String title;
}
Ожидаемый результат — неавторизованный запрос GET в / books / book и авторизованный запрос POST в / book / books
Комментарии:
1. Я отправляю токен через postman и использую базовую аутентификацию. Результат, который я получаю, имеет http-статус 403, что означает, что он неавторизован.
Ответ №1:
Вы используете Spring Boot?
Одна вещь, которая мне кажется странной, заключается в том, что вы ничего не делаете со своим CustomUserDetailsService.
попробуйте добавить в CustomSecurityConfig
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService());
}
Комментарии:
1. Решение не работает. Я автоматически подключаю customUserDetaulsService, чтобы Spring IOC автоматически обрабатывал объект для меня.
Ответ №2:
Проблема была в версии моих зависимостей Spring. Когда я обновил версию, проблема больше не возникала.