2017-09-02 1 views
5

Ich habe ein Problem mit CORS wurde und ich alles versucht habe ich auf Stack-Überlauf und im Grunde nichts finden konnte, die ich auf Google gefunden und hatten kein Glück.Erste ein Beitrag 403 Forbidden mit Frühlings-Boot (VueJS und Axios Frontend)

So habe ich Benutzer-Authentifizierung auf meinem Backend und ich habe eine Login-Seite auf meinem Frontend. Ich habe die Login-Seite mit Axios verbunden, damit ich eine Post-Anfrage machen konnte und versuchte mich anzumelden, aber ich bekam immer Fehler wie "Preflight-Anfrage", also korrigierte ich den Fehler "Post 403 Forbidden".

es so erschien:

POST http://localhost:8080/api/v1/login/ 403 (Forbidden) 

Auch nicht so eindeutig etwas falsch anmelden Postman verwenden, funktioniert aber versuchen, Arbeit ist. Wird Entsendung Klassendateien unter

Auf meinem Backend habe ich eine Klasse namens WebSecurityConfig, die mit allen CORS Sachen beschäftigt:

@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private UserDetailsServiceImpl userDetailsService; 

    @Bean 
    public WebMvcConfigurer corsConfigurer() { 
     return new WebMvcConfigurerAdapter() { 
      @Override 
      public void addCorsMappings(CorsRegistry registry) { 
       registry.addMapping("/**") 
         .allowedMethods("GET", "POST", "HEAD", "PUT", "DELETE", "OPTIONS"); 
      } 
     }; 
    } 

    @Bean 
    public CorsFilter corsFilter() { 
     UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 
     CorsConfiguration config = new CorsConfiguration(); 
     config.setAllowCredentials(true); 
     config.addAllowedOrigin("*"); // TODO: lock down before deploying 
     config.addAllowedHeader("*"); 
     config.addExposedHeader(HttpHeaders.AUTHORIZATION); 
     config.addAllowedMethod("*"); 
     source.registerCorsConfiguration("/**", config); 
     return new CorsFilter(source); 
    } 


    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.headers().frameOptions().disable(); 
     http 
       .cors() 
       .and() 
       .csrf().disable().authorizeRequests() 
       .antMatchers("/").permitAll() 
       .antMatchers("/h2/**").permitAll() 
       .antMatchers(HttpMethod.POST, "/api/v1/login").permitAll() 
       .anyRequest().authenticated() 
       .and() 
       // We filter the api/login requests 
       .addFilterBefore(new JWTLoginFilter("/api/v1/login", authenticationManager()), 
         UsernamePasswordAuthenticationFilter.class); 
     // And filter other requests to check the presence of JWT in header 
     //.addFilterBefore(new JWTAuthenticationFilter(), 
     //  UsernamePasswordAuthenticationFilter.class); 
    } 

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     // Create a default account 
     auth.userDetailsService(userDetailsService); 
//  auth.inMemoryAuthentication() 
//    .withUser("admin") 
//    .password("password") 
//    .roles("ADMIN"); 
    } 
} 

Auf dem Frontend, das in VueJS geschrieben und Axios mit dem Anruf tätigen

<script> 
    import { mapActions } from 'vuex'; 
    import { required, username, minLength } from 'vuelidate/lib/validators'; 

    export default { 
     data() { 
      return { 
       form: { 
        username: '', 
        password: '' 
       }, 
       e1: true, 
       response: '' 
      } 
     }, 
     validations: { 
      form: { 
       username: { 
        required 
       }, 
       password: { 
        required 
       } 
      } 
     }, 
     methods: { 
      ...mapActions({ 
       setToken: 'setToken', 
       setUser: 'setUser' 
      }), 
      login() { 
       this.response = ''; 
       let req = { 
        "username": this.form.username, 
        "password": this.form.password 
       }; 

       this.$http.post('/api/v1/login/', req) 
       .then(response => { 
        if (response.status === 200) { 
         this.setToken(response.data.token); 
         this.setUser(response.data.user); 

         this.$router.push('/dashboard'); 
        } else { 
         this.response = response.data.error.message; 
        } 
       }, error => { 
        console.log(error); 
        this.response = 'Unable to connect to server.'; 
       }); 
      } 
     } 
    } 
</script> 

Also, wenn ich über den Chrome-Tools (Network) debuggt, bemerkte ich, dass die Anforderung OPTIONS durch unten gezeigt geht:

Hier

ist ein Bild von der POST-Fehler:

POST Request Error

Hier ist eine andere Klasse, die die OPTIONS-Anforderung (JWTLoginFilter wie im WebSecurityConfig bezeichnet) behandelt:

public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter { 

    public JWTLoginFilter(String url, AuthenticationManager authManager) { 
     super(new AntPathRequestMatcher(url)); 
     setAuthenticationManager(authManager); 

    } 

    @Override 
    public Authentication attemptAuthentication(
      HttpServletRequest req, HttpServletResponse res) 
      throws AuthenticationException, IOException, ServletException { 
     AccountCredentials creds = new ObjectMapper() 
       .readValue(req.getInputStream(), AccountCredentials.class); 
     if (CorsUtils.isPreFlightRequest(req)) { 
      res.setStatus(HttpServletResponse.SC_OK); 
      return null; 

     } 
     return getAuthenticationManager().authenticate(
       new UsernamePasswordAuthenticationToken(
         creds.getUsername(), 
         creds.getPassword(), 
         Collections.emptyList() 

       ) 
     ); 
    } 

    @Override 
    protected void successfulAuthentication(
      HttpServletRequest req, 
      HttpServletResponse res, FilterChain chain, 
      Authentication auth) throws IOException, ServletException { 
     TokenAuthenticationService 
       .addAuthentication(res, auth.getName()); 
    } 
} 

Antwort

0

Ich hatte die gleiche Art von Problem, bei dem eine GET-Anfrage funktionierte, und dennoch eine POST-Anfrage mit dem Status 403 beantwortet wurde.

Ich habe festgestellt, dass dies in meinem Fall aufgrund des CSRF-Schutzes standardmäßig aktiviert war.

Eine schnelle Art und Weise sicher, von diesem Fall zu machen, ist CSRF zu deaktivieren:

@Configuration 
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    // … 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     // … 
     http.csrf().disable(); 
     // … 
    } 

    // … 

} 

Mehr auf Spring-Security Website-Informationen.

Beachten Sie, dass das Deaktivieren von CSRF nicht immer die richtige Antwort ist, da es aus Sicherheitsgründen da ist.

0

Sie sollten CSRF nicht wie in der Spring Security-Dokumentation mit Ausnahme einiger spezieller Fälle deaktivieren. Dieser Code wird den CSRF-Header auf VUE setzen. Ich habe Vue-Ressource verwendet.

//This token is from Thymeleaf JS generation. 
var csrftoken = [[${_csrf.token}]]; 

console.log('csrf - ' + csrftoken) ; 

Vue.http.headers.common['X-CSRF-TOKEN'] = csrftoken; 

Ich hoffe, dies hilft.