Angular调用SpringBoot接口:POST请求401,GET正常,Postman均正常
问题:Angular POST请求到Spring Boot微服务返回401,GET请求正常
使用Okta官方Angular示例项目测试与Spring Boot应用集成,搭建了带Spring Security的微服务。通过Postman调用接口时GET和POST均正常,但Angular发起POST请求返回401 Unauthorized,服务器日志显示认证为匿名身份;将控制器方法改为GET后问题解决,疑惑POST请求失败的原因。
相关信息
服务器日志
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
Angular组件代码(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] })); }) } }
Spring Security配置(SecurityConfiguration.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(); } }
Spring控制器代码(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); } } }
问题原因与解决办法
核心原因
Angular的HttpClient.post()方法参数传递错误:该方法的第二个参数是请求体数据,第三个参数才是包含headers的配置对象。当前代码把headers当成请求体传递,导致实际请求中根本没有携带Authorization头,Spring Security因此识别为匿名身份,返回401。
修正后的Angular代码
调整http.post的参数顺序,将headers放在配置参数中:
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}` }; // 第二个参数传空请求体(接口无需参数),第三个参数传headers配置 return this.http.post(apiUrl, {}, { headers }).subscribe(data => { this.orders = Object.entries(data).map(entry => ({ name: entry[0], value: entry[1] })); }) }
补充说明
- GET请求正常是因为
HttpClient.get()的第二个参数就是配置对象,之前的调用方式正确,能正常携带Authorization头。 - Postman调用正常是因为手动正确设置了请求头,不存在参数传递错误的问题。
- 控制器方法用
@PostMapping但方法名为getOrders,语义上不合理,建议根据实际功能调整(如改为createOrders),但这不是导致401的直接原因。
内容的提问来源于stack exchange,提问作者softechie
相关产品推荐
相关产品推荐

