简体   繁体   English

Angular 和 Spring Boot - POST 请求成为 OPTIONS

[英]Angular and Spring boot - POST Request become OPTIONS

I'm developing my API using Spring boot (and Spring Security) and the front with Angular.我正在使用 Spring Boot(和 Spring Security)和 Angular 前端开发我的 API。

Thee TypeScript code :你打字稿代码:

return this.http.post<any>('http://localhost:8080/users',
        {
            firstName: 'Clemi',
            lastName: 'Le boss',
            mail: 'clemclem'
        });

My controller :我的控制器:

@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);
    }

}

And the security config :和安全配置:

@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;
    }
}

When I use postman my request works fine.当我使用邮递员时,我的请求工作正常。 But when I use my front every request are turned into OPTIONS request.但是当我使用我的前端时,每个请求都变成了 OPTIONS 请求。 I read multiples articles explaining it's because of Cross Origin Request and could be a 'preflight request' but I don't know how to fix it...我阅读了多篇文章,解释这是因为跨源请求,并且可能是“预检请求”,但我不知道如何解决它...

Any idea ?任何想法 ?

The issue is caused by CORS.该问题是由 CORS 引起的。 You need to accept request from another domain (only for local development) as it is shown here你需要接受来自另一个域(仅适用于本地开发)的要求,因为它显示这里

The behavior is due to CORS .该行为是由于CORS Their are two approaches to deal with this behavior.他们是处理这种行为的两种方法。

  1. ACCEPT HEADER on server end.在服务器端ACCEPT HEADER Indeed this will work but, it is not a good practice to add accept header on your server code.这确实可行,但是在服务器代码上添加accept标头并不是一个好习惯。
  2. PROXY A very common architecture for any application having service , frontend is that they have proxy manager in between like nginx , apache . PROXY对于任何具有service应用程序来说,这是一个非常常见的架构, frontend是它们之间有代理管理器,例如nginxapache But again this works for production env .但这同样适用于production env For development purpose angular cli comes bundled with in-built lite-server which host the live preview on ng serve .Here is the needed configuration required to setup proxy on lite server .出于开发目的, angular cli与内置的lite-server捆绑在一起,它在ng serve上托管实时预览。这是在lite server上设置代理所需的配置。

i.一世。 Create a file call proxy-config.json at root of the angular project.在 angular 项目的根目录创建一个文件调用proxy-config.json ii. ii. Add Following content based on the server address.根据服务器地址添加以下内容。

{
  "/api": {
    "target": "http://localhost:8080/",
    "changeOrigin": true,
    "secure": false,
    "pathRewrite": {
       '^/api': ''
     }
   }
}

/api is the proxy part of the all the end points from your angular application /api是 angular 应用程序中所有端点的proxy部分

http://localhost:8080/accounts(actual server endpoint) -----> http://localhost:8080/api/accounts(proxy end point) http://localhost:8080/accounts(actual server endpoint) -----> http://localhost:8080/api/accounts(proxy end point)

Then modify following script command in package.json然后在package.json修改以下脚本命令

"start": "ng serve --proxy-config proxy.config.json --port 4200",

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM