2016-07-21 16 views
6

CORSの問題をデバッグしているうちに、次のような現象が発生しました。以下の場合CORSのプリフライト要求が標準ヘッダーのために失敗しました

curl -v 'https://www.example.com/api/v1/users' -X OPTIONS -H 'Access-Control-Request-Method: POST' -H 'Origin: http://example.com' -H 'Accept-Encoding: gzip,deflate,sdch' -H 'Accept-Language: es-ES,es;q=0.8,en;q=0.6' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36' -H 'Accept: */*' -H 'Referer: http://example.com/users/new' -H 'Connection: keep-alive' -H 'Access-Control-Request-Headers: accept, x-api-key, content-type' 

この要求に対するサーバからの応答:クロム(クロム単独でCURLで書き換え)以下のオプションプリフライト要求を行う

< HTTP/1.1 403 Forbidden 
< Date: Thu, 21 Jul 2016 14:16:56 GMT 
* Server Apache/2.4.7 (Ubuntu) is not blacklisted 
< Server: Apache/2.4.7 (Ubuntu) 
< X-Content-Type-Options: nosniff 
< X-XSS-Protection: 1; mode=block 
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate 
< Pragma: no-cache 
< Expires: 0 
< Strict-Transport-Security: max-age=31536000 ; includeSubDomains 
< X-Frame-Options: SAMEORIGIN 
< Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH 
< Content-Length: 20 
< Keep-Alive: timeout=5, max=100 
< Connection: Keep-Alive 

応答「無効の本体でありますCORSの要求です。私は、ヘッダを削除要求「アクセス制御リクエスト・メソッド」(とのみそのヘッダ)を繰り返すとOPTIONS要求は、次のREPONSEに成功:

< HTTP/1.1 200 OK 
< Date: Thu, 21 Jul 2016 14:21:27 GMT 
* Server Apache/2.4.7 (Ubuntu) is not blacklisted 
< Server: Apache/2.4.7 (Ubuntu) 
< X-Content-Type-Options: nosniff 
< X-XSS-Protection: 1; mode=block 
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate 
< Pragma: no-cache 
< Expires: 0 
< Strict-Transport-Security: max-age=31536000 ; includeSubDomains 
< X-Frame-Options: SAMEORIGIN 
< Access-Control-Allow-Headers: origin, content-type, accept, x-requested-with, x-api-key 
< Access-Control-Max-Age: 60 
< Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS 
< Access-Control-Allow-Origin: * 
< Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH 
< Content-Length: 0 
< Keep-Alive: timeout=5, max=100 
< Connection: Keep-Alive 

はしかし、問題のヘッダはとてもそれが必要CORS spec standard headerです要求が成功するのを防ぐのではないでしょうか?このヘッダがこのような動作を引き起こすのはなぜですか?

また、Chromeで作成したリクエストを動作させるためにサーバーから送信されたアクセス制御ヘッダーを調整するにはどうすればよいですか?

ところで、私はChrome 36.0を使用していますが、サーバーはSpringブートを使用しており、CORSヘッダーはSpringによって管理されています。

Firefox(v47.0)でリクエストが行われた場合、動作は異なりますが、アナログ結果が表示されます。 Firefoxはプリフライトリクエストを送信しなくても、POSTリクエストを直接送信します。これは応答として403 Forbiddenを受け取ります。ただし、「cURLとしてコピー」オプションを使用して要求をコピーし、端末ウィンドウからそれを繰り返すと、応答に正しいCORSヘッダーが送信されます。

任意のアイデア?

更新:Firefoxは(プラグインライブHTTPヘッダによって示されるように)プリフライトOPTIONS要求を送信しますが、Firebugのマスク、それを、その両方のブラウザでの動作もまったく同じん。どちらのブラウザーでも、「Access-control-request-method」ヘッダーが要求を失敗させます。

答えて

14

多くの苦労の末、私はついにこの問題を発見しました。

@RequestMapping(value= "/api/**", method=RequestMethod.OPTIONS) 
public void corsHeaders(HttpServletResponse response) { 
    response.addHeader("Access-Control-Allow-Origin", "*"); 
    response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); 
    response.addHeader("Access-Control-Allow-Headers", "origin, content-type, accept, x-requested-with"); 
    response.addHeader("Access-Control-Max-Age", "3600"); 
} 

私はデフォルトの春でdefault CORS processorを使用していることを知らなかった、そして私の要求のマッピングに干渉しているようだ。私はこのように、OPTIONSのトラフィックを処理するために、春に要求のマッピングを構成しました。リクエストマッピングを削除し、適切なリクエストマッピングに@CrossOrigin注釈を追加することで問題は解決されました。

+2

限り、あなたのSecurityConfigurationクラスでCORS() yはApacheで設定した場合、通常のCORS処理を中断します。 CorsFilterを設定するか、ここのアドバイスに従うかのように見えます - https://spring.io/guides/gs/rest-service-cors/ – chrismarx

+1

この投稿は参考になりました:http://stackoverflow.com /質問/ 9521690 /ハウツーハンドル-HTTP-オプション-とスプリング-MVC DispatchServletは、オプションの要求に沿って通過するように構成する必要があり、そうでなければ、マップされた要求に達することはありません:< ... をサーブレット名> yourServletのorg.springframework.web.servlet.DispatcherServlet ​​dispatchOptionsRequest true 1 ... – Mike

0

私は答えとしてこれを追加しました。なぜなら、私は一番上の投票回答のためにそれをうまくフォーマットできなかったからです。

私もこれはポスト役に立った:How to handle HTTP OPTIONS with Spring MVC?

DispatchServletは、オプションの要求に沿って通過するように構成する必要があり、そうでなければ、マッピングされた要求に達することはありません:私は同じ問題を持っていた

... 
    <servlet> 
    <servlet-name>yourServlet</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <init-param> 
     <param-name>dispatchOptionsRequest</param-name> 
     <param-value>true</param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
    </servlet> 
... 
0

を。私は、Spring MVC設定でCORSメソッドに 'OPTIONS'を追加することで解決しました。

@Configuration 
@EnableWebMvc 
@ComponentScan 
public class RestApiServletConfig extends WebMvcConfigurerAdapter { 

    @Override 
    public void addCorsMappings(CorsRegistry registry) { 
     super.addCorsMappings(registry); 
     registry.addMapping("/**") 
       .allowedOrigins("http://localhost:3000", "http://localhost:8080") 
       .allowedMethods("GET", "PUT", "POST", "DELETE", "OPTIONS"); 
    } 
} 
0

この アドオンのためので、私も同じ問題に直面し、春ブーツで、この後

@Configuration 
@EnableWebMvc 
public class WebConfig extends WebMvcConfigurerAdapter { 
    @Override 
    public void addCorsMappings(CorsRegistry registry) { 
     registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*") 
       .allowedHeaders("*"); 
    } 
} 

をグローバルCORSの問題を有効にするための解決策を見つける、我々は、また、春のセキュリティレベルでCORSを有効にする必要がありますはい、どのようなヘッドの旅、春はactuallそれ、デフォルトのCORSのプロセッサを持っていますが、その設定されていない限りWebSecurityConfigurerAdapter

@Override 
    protected void configure(HttpSecurity httpSecurity) throws Exception { 

     httpSecurity 
       .cors() 
       .and() 
       .csrf().disable() 
       .authorizeRequests().. 

    } 
関連する問題