如何配置 Spring Security 以避免 405 Method Not Allowed for PUT request from Angular?

Posted

技术标签:

【中文标题】如何配置 Spring Security 以避免 405 Method Not Allowed for PUT request from Angular?【英文标题】:How to configure Spring Security to avoid 405 Method Not Allowed for PUT request from Angular? 【发布时间】:2021-11-18 19:25:24 【问题描述】:

我正在练习 Angular + Spring(使用 Spring Security 基本身份验证)。

我无法发出 PUT 请求来更新我的实体。

服务器响应 405 Method Not Allowed。

HTTP/1.1 405 
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *
Set-Cookie: JSESSIONID=90B569C7D540CC684DB87C9FCEEED922; Path=/; HttpOnly
Allow: GET, POST
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sun, 26 Sep 2021 08:24:47 GMT
Keep-Alive: timeout=60
Connection: keep-alive

有一个使用 POST 请求的解决方法。我试过了,效果很好。

但我确实想知道如何配置 Spring Security 以使 PUT 请求有效。

我的 Angular 和 Spring 实践代码:

由 Angular 向服务器发送 PUT 请求。

@Injectable(
  providedIn: 'root'
)
export class HeroService 

  private heroesUrl = 'http://localhost:8080/api/heroes';

  private httpOptions = 
    headers: new HttpHeaders(
      'Content-Type': 'application/json',
      'Authorization': 'Basic dXNlcjpwYXNzd29yZA=='
    )
  ;

  /** PUT: update the hero on the server */
  updateHero(hero: Hero): Observable<any> 
    return this.http.put(this.heroesUrl, hero, this.httpOptions).pipe(
      tap(_ => this.log(`updated hero id=$hero.id`)),
    );
  

它是put请求的控制器

@RestController
@CrossOrigin
@RequestMapping(path = ["/api/heroes"], produces = ["application/json"])
class HeroController(private val heroService: HeroService) 

    @PutMapping(path = ["/id"], consumes = ["application/json"])
    fun updateOrCreate(@PathVariable id: Long, @RequestBody hero: Hero): ResponseEntity<Hero> 
        return if (heroService.existsById(id)) 
            hero.id = id;
            ResponseEntity<Hero>(heroService.update(hero), HttpStatus.OK);
         else 
            ResponseEntity<Hero>(heroService.create(hero), HttpStatus.CREATED);
        
    

【问题讨论】:

【参考方案1】:

最后,我找出了问题所在,学到了两件事。

    PUT 请求的路径不正确。缺少 ID 作为路径参数。当前代码如下:
  /** PUT: update the hero on the server */
  updateHero(hero: Hero): Observable<any> 
    return this.http.put(`$this.heroesUrl/$hero.id`, hero, this.httpOptions).pipe(
      tap(_ => this.log(`updated hero id=$hero.id`)),
      catchError(this.handleError<any>('updateHero'))
    );
  
    我了解到 Spring 中有一个 DEBUG 日志。打开调试日志后,我发现了这个问题。
logging.level.org.springframework.security=DEBUG

【讨论】:

在询问堆栈溢出问题之前,您应该学会如何调试您的应用程序。将其作为未来的课程。

以上是关于如何配置 Spring Security 以避免 405 Method Not Allowed for PUT request from Angular?的主要内容,如果未能解决你的问题,请参考以下文章

如何在spring security避免登录页面素材文件被禁止加载

如何配置 Spring Security 以允许在 JSP 页面中使用 hasPermission?

如何配置 Spring Boot 和 Spring Security 以支持表单登录和 Google OAuth2 登录

Spring security 如何设置才能避免拦截到静态资源

如何在 Spring Security 中配置资源服务器以使用 JWT 令牌中的附加信息

如何使用 Spring Security SAML 配置远程发现?