Angular 和 Spring 启动 - POST 请求成为 OPTIONS
Posted
技术标签:
【中文标题】Angular 和 Spring 启动 - POST 请求成为 OPTIONS【英文标题】:Angular and Spring boot - POST Request become OPTIONS 【发布时间】:2020-04-18 05:31:34 【问题描述】:我正在使用 Spring boot(和 Spring Security)和 Angular 开发我的 API。
你的 TypeScript 代码:
return this.http.post<any>('http://localhost:8080/users',
firstName: 'Clemi',
lastName: 'Le boss',
mail: 'clemclem'
);
我的控制器:
@RestController
@RequestMapping(path = "/users")
public class UserController
@Autowired
private UserService userService;
...
@PostMapping()
public ResponseEntity<Object> addUser(Principal principal, @RequestBody User user)
User savedUser = userService.save(user);
return new ResponseEntity<Object>(HttpStatus.OK);
以及安全配置:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
UserService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
@Override
protected void configure(HttpSecurity http) throws Exception
http.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(new Http403ForbiddenEntryPoint()
)
.and()
.authenticationProvider(getProvider())
.formLogin()
.loginProcessingUrl("/login")
.successHandler(new AuthentificationLoginSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new AuthentificationLogoutSuccessHandler())
.invalidateHttpSession(true)
.and()
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/logout").permitAll()
.antMatchers(HttpMethod.GET, "/users/**").authenticated()
.antMatchers(HttpMethod.DELETE, "/users/**").hasRole("ADMIN")
.antMatchers(HttpMethod.PUT).hasRole("USER")
.anyRequest().permitAll()
.and()
.httpBasic();
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
return new BCryptPasswordEncoder();
private class AuthentificationLoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException
response.setStatus(HttpServletResponse.SC_OK);
private class AuthentificationLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException
response.setStatus(HttpServletResponse.SC_OK);
@Bean
public AuthenticationProvider getProvider()
AuthService provider = new AuthService();
provider.setUserDetailsService(userDetailsService);
provider.setPasswordEncoder(bCryptPasswordEncoder());
return provider;
当我使用邮递员时,我的请求工作正常。但是当我使用我的前端时,每个请求都变成了 OPTIONS 请求。我阅读了多篇文章,解释这是因为 Cross Origin Request 并且可能是“预检请求”,但我不知道如何解决它......
有什么想法吗?
【问题讨论】:
在生产中,您是否计划从同一个 URL 为 Angular 应用程序和 REST 服务提供服务?如果是这样,让 ng 充当 Spring 的反向代理:github.com/angular/angular-cli/blob/master/docs/documentation/…,并从您的 URL 中删除“localhost:8080”(这对您自己的开发机器没有任何意义)。 您需要将HttpMethod.OPTIONS
列入白名单
【参考方案1】:
该行为是由于 CORS
造成的。它们是处理这种行为的两种方法。
ACCEPT HEADER
在服务器端。这确实可行,但在服务器代码中添加 accept
标头不是一个好习惯。
PROXY
对于任何具有service
、frontend
的应用程序来说,一个非常常见的架构是它们之间有代理管理器,例如nginx
、apache
。但这同样适用于production env
。出于开发目的,angular cli
与内置的lite-server
捆绑在一起,它在ng serve
上托管实时预览。这是在lite server
上设置代理所需的配置。
我。在 Angular 项目的根目录下创建一个文件调用 proxy-config.json
。
ii.根据服务器地址添加关注内容。
"/api":
"target": "http://localhost:8080/",
"changeOrigin": true,
"secure": false,
"pathRewrite":
'^/api': ''
/api
是您的 Angular 应用程序中所有端点的 proxy
部分
http://localhost:8080/accounts(actual server endpoint)
-----> http://localhost:8080/api/accounts(proxy end point)
然后在package.json
中修改如下脚本命令
"start": "ng serve --proxy-config proxy.config.json --port 4200",
【讨论】:
【参考方案2】:问题是由 CORS 引起的。您需要接受来自另一个域的请求(仅用于本地开发),如图所示here
【讨论】:
以上是关于Angular 和 Spring 启动 - POST 请求成为 OPTIONS的主要内容,如果未能解决你的问题,请参考以下文章
如何使基本身份验证作为 Angular JS/Spring 启动应用程序中 keycloak 的替代品
spring bootRun 和 Angular buildWatch 使用 Gradle
减少 Spring Boot 可执行 jar Angular App 的磁盘空间
删除表中的每条记录时重新启动Id = 1? (角度 + Spring Boot + MySQL)