通过Angular到Springboot访问POST失败但GET成功,Postman适用于GET和POST

问题描述 投票:0回答:1

我正在使用示例 Angular 应用程序来测试 Okta 与 springboot 应用程序的集成。 前端示例:https://github.com/okta-samples/okta-angular-sample

我有一个带有控制器的 springboot 微服务并启用了 spring security。我可以使用邮递员到达端点,没有任何问题,但是当通过角度发出请求时,我得到 401 Unauthorized 以下是服务器日志:

2024-01-07 19:19:18.499 DEBUG 10476 --- [nio-8040-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.4g.account.controller.AccountController#getOrders()
2024-01-07 19:19:18.511 DEBUG 10476 --- [nio-8040-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
2024-01-07 19:19:18.520 DEBUG 10476 --- [nio-8040-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor    : Failed to authorize filter invocation [POST /account/orders] with attributes [authenticated]
2024-01-07 19:19:18.524 DEBUG 10476 --- [nio-8040-exec-1] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext
2024-01-07 19:19:18.524 DEBUG 10476 --- [nio-8040-exec-1] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request

profile.component.ts

import {HttpClient} from '@angular/common/http';
import { Component, Inject, OnInit } from '@angular/core';
import { IDToken, OktaAuth } from '@okta/okta-auth-js';
import { OKTA_AUTH } from '@okta/okta-angular';

@Component({
  selector: 'app-profile',
  templateUrl: './profile.component.html',
  styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
  orders!: { name: string; value: unknown }[];

  constructor(@Inject(OKTA_AUTH) public oktaAuth: OktaAuth,private http: HttpClient) {
  }

  async ngOnInit() {
    await this.getOrders();
  }
  async getOrders() {
    const accessToken: AccessToken = await this.oktaAuth.tokenManager.get('accessToken') as AccessToken;
    const apiUrl = 'http://localhost:8090/account/orders';
    const headers = {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${accessToken.accessToken}`
    };
    return this.http.post(apiUrl, { headers }).subscribe(data => {
      this.orders = Object.entries(data).map(entry => ({ name: entry[0], value: entry[1] }));
  })
}
}

安全配置.java

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    Environment environment;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated().and().oauth2ResourceServer()
                .authenticationManagerResolver(new JwtIssuerAuthenticationManagerResolver("https://xxxx.okta.com/oauth2/default"));
        http.cors();
    }

}

AccountController.java

@RestController
@CrossOrigin(origins = {"http://localhost:4200"})
@RequestMapping("/account")
public class AccountController {
    @Autowired
    private SecurityContextAccessor securityContextAccessor;
    @Autowired
    private OrderService orderService;
    @PostMapping(value = "/orders")
    public @ResponseBody ResponseEntity<String> getOrders() {
        try{
            return new ResponseEntity<>(orderService.getOrders(securityContextAccessor.getJwtToken()), HttpStatus.OK);
        }catch(AccountException ae){
            return new ResponseEntity<>("", HttpStatus.FORBIDDEN);
        }
    }
}

更新

当我将控制器从 POST 更改为 GET 时,问题得到解决,想知道为什么 POST 请求失败?

angular spring spring-boot postman okta
1个回答
0
投票

根据 当前建议您的 Angular 应用程序不应配置为 OAuth2“公共”客户端(从授权服务器获取令牌)。相反,您应该使用 BFF 模式,并在服务器上运行 OAuth2“机密”客户端,并在 Angular 和 BFF 之间使用会话和 CSRF 保护(其配置错误可能是导致当前问题的原因)授权请求。我为此编写了一个教程,它适用于任何 OIDC 提供商(包括 Okta)。

请注意,我第一个链接的帖子是由 Spring Security 团队在 2021 年中编写的,自那时起教程应该已修复,但是......

此外,

WebSecurityConfigurerAdapter
来自旧版本的 Spring Security,只有非常不推荐使用的版本不支持定义 Web 安全性的新方法(公开
SecurityFilterChain
beans)。你应该切换到那个。

© www.soinside.com 2019 - 2024. All rights reserved.