从 Angular 客户端到 Spring 引导服务器的简单 POST 请求给出状态 403 错误
Posted
技术标签:
【中文标题】从 Angular 客户端到 Spring 引导服务器的简单 POST 请求给出状态 403 错误【英文标题】:Simple POST request from Angular client to Spring boot server gives status 403 error 【发布时间】:2021-08-15 22:43:51 【问题描述】:当我尝试从 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);
错误
Spring 引导服务器没有接收到请求。
我的代码有什么问题?
【问题讨论】:
您是否附上了正确的标题? spring boot 端的日志是什么?您应该提供日志以找到解决方案。 spring boot端没有log。我确实添加了调试点,但它没有被触发。 您是否尝试过使用 postman 之类的 Spring Boot 应用程序?是否按预期工作? 我以前没有使用过 Postman,但感谢您让我了解该工具。之前我使用 Python pip 之类的东西来检查我的请求... 【参考方案1】:检查安全配置我认为有问题。
【讨论】:
【参考方案2】:我必须对我的安全配置进行一项更改。 我确实禁用了 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("noop123")
.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;
【讨论】:
以上是关于从 Angular 客户端到 Spring 引导服务器的简单 POST 请求给出状态 403 错误的主要内容,如果未能解决你的问题,请参考以下文章
我无法向自己的 Spring 引导服务器发出 Angular Http 请求
将 Blob 数据作为 MultipartFile 从 Angular6 客户端发送到 Spring Boot API
Angular 从 Spring RestController 获取图像并缓存它
Spring Boot + Angular 5 - http.post 空值