如何解决从 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);
}
}
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;
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。