从 Angular 客户端到 Spring 启动服务器的简单 POST 请求给出状态 403 错误

问题描述

当我尝试从 Angular 客户端向 Spring Boot 服务器执行简单的 POST 请求时,我收到此错误 403。

以下代码是 HTML 模板...

HTML 模板

<!-- Create book html -->
<div class="content-container">
  <div class="content-area">
  
    <!-- Back button -->
    <div> 
      <button class="btn btn-danger btn-block" (click)="back()">Back</button>
    </div>

    <p style="font-weight: bold; color: green;">Please enter all the details in-order to enter a new book!!!</p><br/>

    <p>{{book | json}}<p>

    <form (ngSubmit)="onCreate()">
      <!-- Book name -->
      <label for="name"><b>Book name:</b></label><br/>
      <input type="text" name="name" class="formField" size="100" placeholder="Ex: Bram Stoker's Dracula" [(ngModel)]="book.name"/><br/><br/>
    
      <!-- Author ID -->
      <label for="authorid"><b>Author ID:</b></label><br/>
      <input type="text" name="authorid" class="formField" size="50" placeholder="Ex: 100015" [(ngModel)]="book.authorID"/><br/><br/>

      <!-- Publication ID -->
      <label for="publicationid"><b>Publication ID:</b></label><br/>
      <input type="text" name="publicationid" class="formField" size="50" placeholder="Ex: 200015" [(ngModel)]="book.publicationID"/><br/><br/>
      
      <!-- Publication date -->
      <label for="publicationdate"><b>Publication Date:</b></label><br/>
      <input type="date" name="publicationdate" class="formField" [ngModel]="book.publicationDate | date:'yyyy-MM-dd'" (ngModelChange)="book.publicationDate = $event"/><br/><br/>
      
      <!-- Description -->
      <label for="description"><b>Book Description:</b></label><br/>
      <textarea name="description" class="formField" rows="3" cols="100" placeholder="Describe about the book here..." [(ngModel)]="book.description"></textarea><br/><br/>

      <!-- Edition -->
      <label for="edition"><b>Book Edition:</b></label><br/>
      <input type="text" name="edition" class="formField" size="50" placeholder="Ex: 5" [(ngModel)]="book.edition"/><br/><br/>

      <!-- Category -->
      <label for="category"><b>Book Category:</b></label><br/>
      <input type="text" name="category" class="formField" size="50" placeholder="Ex: 3" [(ngModel)]="book.category"/><br/><br/>

      <!-- rating -->
      <label for="rating"><b>Book rating:</b></label><br/>
      <input type="text" name="rating" class="formField" size="50" placeholder="Ex: 10" [(ngModel)]="book.rating"/><br/><br/>
      
      <div style="text-align:center; width:100%;">
         <button type="submit" class="btn btn-primary btn-block">Create</button>
     </div>
    </form>

  </div>
</div>

以下代码是组件...

组件

import { Component,OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { Book } from '../services/data';
import { Router } from '@angular/router';
import { BookService } from '../services/book.service';

//Create book componenet 

@Component({
  selector: 'app-createbook',templateUrl: './createbook.component.html',styleUrls: ['./createbook.component.css']
})
export class CreatebookComponent implements OnInit {
  //Attributes
  book = {
    bookID: 0,name: '',authorID: 0,publicationID: 0,publicationDate: new Date,description: '',edition: 0,category: 0,rating: 0
  };

  //Constructor of the CreatebookComponent. 
  constructor(private location: Location,private router: Router,private bookService: BookService) { }

  //Component life cycle hook. Executes once componenet initiated. 
  ngOnInit(): void { }
  
  //Executes on book create. 
  onCreate() {
      this.bookService.createBook(this.book);
  }

  //Responsible for handling the back mechanism. 
  back() {
      this.location.back();
  }

}

以下代码是执行 POST 请求的服务类...

服务

import { Injectable } from '@angular/core';
import { HttpClient,HttpHeaders } from '@angular/common/http';
import { Router } from '@angular/router';
import { Book } from './data';

//Service for books in library client 

@Injectable()
export class BookService{
  //Attributes 
  recentBooks: Array<Book> = []; 
  createdBook: Book; 

  //Constructor of BookService 
  constructor(private httpClient: HttpClient,private router: Router) { }
  
  //Return the recent book array. 
  get(): Book[] {
      return this.recentBooks;
  }
  
  //Return recent books. 
  getRecentBooks() {
      return this.httpClient.get<Array<Book>>("http://localhost:8080/book/recents");//.subscribe(book => this.recentBooks=book);
      //return this.recentBooks;
  }
  
  //Responsible for creating given book. 
  createBook(theBook: any): void {
      this.httpClient.post("http://localhost:8080/book/create",theBook,{ headers: new HttpHeaders().set("Content-type","application/json") }).subscribe(result => this.redirectHome());
  }
  
  //Redirect to home page 
  redirectHome() {
      this.router.navigate(['/home']);
  }
  
}

以下代码显示了 spring boot REST 控制器代码...

REST 控制器

package com.example.LibraryServer.RestControllers;

import com.example.LibraryServer.Entities.Book;
import com.example.LibraryServer.Repositories.BookRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

/**
 * REST controller for books.
 */
@Slf4j //Lombok annotation for logger
@RestController
@RequestMapping(path = "/book",produces = "application/json")
@CrossOrigin(origins = "http://localhost:4200") //Cross-origin resource sharing
public class BookController {

    private final BookRepository bookRepo;

    /**
     * Constructor of BookController.
     * @param theBookRepository BookRepository
     */
    @Autowired
    public BookController(BookRepository theBookRepository) {
        this.bookRepo = theBookRepository;
    }

    /**
     * Responsible for returning recent books.
     * Returns maximum 12 most recently created books.
     * @return Iterable<Book>
     */
    @GetMapping("/recents")
    public Iterable<Book> recentBooks() {
        log.info("*****LibrarySystem LOGGER***** @GetMapping(/recents) -> REST endpoint executed");
        return bookRepo.recent();
    }

    /**
     * Responsible for returning the book for the given book ID.
     * @param theBookID int
     * @return ResponseEntity<Book>
     */
    @GetMapping("/{id}")
    public ResponseEntity<Book> getBook(@PathVariable("id") int theBookID) {
        log.info("*****LibrarySystem LOGGER***** @GetMapping(/{id}) -> REST endpoint executed");
        Book book = bookRepo.getByID(theBookID);
        if (book != null) {
            return new ResponseEntity<>(book,HttpStatus.OK);
        }
        else {
            return new ResponseEntity<>(null,HttpStatus.NOT_FOUND);
        }
    }

    /**
     * Responsible for deleting the book for the given book ID.
     * @param theBookID int
     */
    @DeleteMapping("/{id}")
    public void delete(@PathVariable("id") int theBookID) {
        log.info("*****LibrarySystem LOGGER***** @DeleteMapping(/{id}) -> REST endpoint executed");
        bookRepo.delete(theBookID);
    }

    /**
     * Responsible for persisting the given book.
     * @param theBook Book
     * @return Book
     */
    @PostMapping(path = "/create",consumes = "application/json")
    @ResponseStatus(HttpStatus.CREATED)
    public Book save(@RequestBody Book theBook) {
        log.info("*****LibrarySystem LOGGER***** @PostMapping -> REST endpoint executed");
        return bookRepo.save(theBook);
    }

}

错误

enter image description here

Spring 启动服务器未收到请求。

请帮助我找出我的代码有什么问题,并提前感谢您在我的问题上花费的时间。

解决方法

检查安全配置我认为有问题

,

终于找到问题所在了。在我的安全配置中,我必须进行一项更改。 我确实禁用了 CSRF(跨站点请求伪造),这阻止了我的 POST 请求。

package com.example.LibraryServer.Security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

/**
 * Class responsible for security configurations.
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * Responsible for user security configuration.
     * Overridden from WebSecurityConfigurerAdapter level.
     * @param theHttpSecurity HttpSecurity
     * @throws Exception - Exception upon security configuration.
     */
    @Override
    protected void configure(HttpSecurity theHttpSecurity) throws Exception {
        theHttpSecurity.authorizeRequests()
                .antMatchers("/**").access("permitAll")
                .and().cors().and().csrf().disable();
    }

    /**
     * Responsible for configuring user-store.
     * Overridden from WebSecurityConfigurerAdapter level.
     * @param theAuthentication AuthenticationManagerBuilder
     * @throws Exception - Exception upon user store creation.
     */
    @Override
    public void configure(AuthenticationManagerBuilder theAuthentication) throws Exception {
        theAuthentication.inMemoryAuthentication()
                .withUser("sankalpa")
                .password("{noop}123")
                .authorities("ROLE_USER");
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**",configuration);
        return source;
    }

}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...