Put 请求在 Spring Web 中给出错误 401/403

时间:2021-07-12 11:29:17

标签: java spring-boot hibernate spring-mvc spring-data-jpa

我有一个简单的 PUT 请求,它在本地 h2 数据库中连续保存一本书。使用邮递员,当我先发送请求,然后再发送请求时,它会返回 401 错误 - 没有数据。截图:1First PUT Request。但是,如果我一个接一个地执行请求(GET 请求,成功执行)Successful GET Request,PUT 请求返回 403 禁止错误403 Error。我使用本地 h2 内存数据库,并使用此代码填充它(我还设置了一个架构 - 否则它无法识别表名):

DROP TABLE IF EXISTS BOOKS;
CREATE TABLE BOOKS(
isbn LONG  AUTO_INCREMENT PRIMARY KEY,
count_books INT NOT NULL,
author VARCHAR(30) NOT NULL,
name VARCHAR(30) NOT NULL UNIQUE,
description VARCHAR(250)
);

INSERT INTO BOOKS (count_books, author, name, description) VALUES
  (2,'Иван Вазов', 'Под Игото', 'В малко градче пристига странник и им показва значението на свободата'),
  (4,'Тютюн', 'Димитър Димов', 'История за човешки характери, поквара и любов на фона на ВСВ.'),
  (6,'Клетниците', 'Виктор Юго', 'Разтърсваща история за човешкия падеж и неговото възстановяване.');

至于 Rest API,我使用 Spring Boot,以及 Web、H2、PostGre 和 OAuth 2.0(未来)。这是我的服务类(充当 DAO):

package Library.demo.dao;

import Library.demo.entities.Books;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.LinkedList;

@Service
public class BooksDAOImpl {
    @Autowired
    BookRepository bookRepository;

    public LinkedList<Books> get_all_books() {
        LinkedList<Books> books = new LinkedList<>();
            for(Books book : bookRepository.findAll()) {
                books.add(book);
            }
        System.out.println(bookRepository.count());
        return books;
    }
    public void addBook_admin(int count, String name, String author, String description){
        Books book = new Books(count,name, author,description);
        bookRepository.save(book);
        System.out.println(bookRepository.count());
    }

}

这是我的 REST 控制器类,用于向数据库添加书籍:

package Library.demo.command;

import Library.demo.dao.BooksDAOImpl;
import org.hibernate.NonUniqueObjectException;
import org.hibernate.exception.JDBCConnectionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;

import java.util.InputMismatchException;

@RestController
public class Add_book_admin_command {
    @Autowired
    BooksDAOImpl bookDAO;

    @PutMapping("/books/add")
    public void execute(@RequestParam int count_books, @RequestParam String author, @RequestParam String name, @RequestParam String description) {
        try {
            bookDAO.addBook_admin(count_books, author, name, description);
        }catch (InputMismatchException ime){
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Wrong type of information");
        }catch (JDBCConnectionException jdbcConnectionException){
            throw new ResponseStatusException(HttpStatus.BAD_GATEWAY, "Error connecting to database");
        }catch (NonUniqueObjectException objectException){
            throw new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE, "Book already exists");
        }
    }
}

这是我获取所有书籍的控制器:

package Library.demo.command;

import Library.demo.dao.BooksDAOImpl;
import Library.demo.entities.Books;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.LinkedList;


@RestController
public class List_all_books_admin_command {
    @Autowired
    BooksDAOImpl bookDAO;
    @GetMapping("/books/all")
    public LinkedList<Books> execute() {
        return bookDAO.get_all_books();
    }


}

还有我的 application.settings 文件:

spring.datasource.url=jdbc:h2:mem:test;
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.jpa.hibernate.ddl-auto=none
security.basic.enable= false
security.ignored=/**

我的实体类是书籍:

package Library.demo.entities;

import javax.persistence.*;

@Entity(name = "BOOKS")
public class Books {

    @Id
    @GeneratedValue
    private long isbn;

    private int count_books;

    private String author;

    private String name;

    private String description;

    public Books( int count_books, String author, String name, String description) {
        this.count_books = count_books;
        this.author = author;
        this.name = name;
        this.description = description;
    }

    public Books() {
    }


    public long getIsbn() {
        return isbn;
    }

    public void setIsbn(int isbn) {
        this.isbn = isbn;
    }

    public int getCount() {
        return count_books;
    }

    public void setCount(int count) {
        this.count_books = count;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

程序构建得很好,控制台输出中没有异常,即使 PUT 请求失败。我对 Spring 框架还很陌生,因此将不胜感激 :)

1 个答案:

答案 0 :(得分:0)

答案 - 通过 WebSecurityConfig 类关闭 csrf。 代码片段:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http.cors().and().csrf().disable();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Collections.singletonList("*"));
        configuration.setAllowedMethods(Collections.singletonList("*"));
        configuration.setAllowedHeaders(Collections.singletonList("*"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

应该可以解决问题