2015-12-07 22 views
5

私は、NginxをSpringブートアプリケーションのリバースプロキシとして使用しています。私はまた、sockjsとstompメッセージとWebsocketを使用します。NginxリバースプロキシWebsocket認証 - HTTP 403

ここにコンテキスト設定があります。ここで

<websocket:message-broker application-destination-prefix="/app"> 
    <websocket:stomp-endpoint path="/localization" > 
     <websocket:sockjs/> 
    </websocket:stomp-endpoint> 
    <websocket:simple-broker prefix="/topic" /> 
</websocket:message-broker> 

は、クライアントのコードです:

var socket = new SockJS(entryPointUrl); 
var stompClient = Stomp.over(socket); 

var _this = this; 

stompClient.connect({}, function() { 
    stompClient.subscribe('/app/some-url', function (message) { 
     // do some stuff 
    }); 
}); 

私はまた、あなたは春のセキュリティ一部のコンテンツを保護するために。

@Configuration 
@Order(4) 
public static class FrontendSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.authorizeRequests() 
       .antMatchers("/js/**", "/css/**", "/webjars/**").permitAll() 
       .anyRequest().authenticated() 
       .and() 
       .formLogin().loginPage("/login").permitAll() 
       .and() 
       .logout().permitAll(); 
    } 

} 

Nginxリバースプロキシの背後にこのアプリケーションを実行すると、すべてがうまくいきます。

proxy_pass http://testsysten:8080; 

    proxy_set_header X-Real-IP $remote_addr; 
    proxy_set_header Host $host; 
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 

    # WebSocket support (nginx 1.4) 
    proxy_http_version 1.1; 
    proxy_set_header Upgrade $http_upgrade; 
    proxy_set_header Connection $http_connection; 

    # Max body size 
    client_max_body_size 10M; 

接続は常にHTTP 403コードで失敗します。

私はバージョン1.9.7を使用しています。

クライアントが認証されない理由は何ですか?

私はthis oneのような同様の質問を知っていますが、解決策はまったく機能しません。

更新

私はHTTP経由でアプリケーションを実行することができました。 Nginxの設定でCSRFトークンを渡す必要があります。新しい設定は次のとおりです。

HTTPS経由のリダイレクトのみが欠落しています。春のログに次のエントリを参照します

o.s.w.s.s.t.h.DefaultSockJsService - Processing transport request: GET http://testsystem:80/localization/226/3mbmu212/websocket 

をnginxのプロキシは、右ポートに書き換える必要があるように思えます。

答えて

7

私は自分でこの問題を解決しました。 WebsocketとSpring Securityを使いたい場合、Nginxは基本的にいくつかのヘッダ値を渡す必要があります。次の行は、あなたのnginxの設定ファイルにlocationセクションに追加する必要があります、私は同様の問題に直面していた

# Pass the csrf token (see https://de.wikipedia.org/wiki/Cross-Site-Request-Forgery) 
    # Default in Spring Boot and required. Without it nginx suppresses the value 
    proxy_pass_header X-XSRF-TOKEN; 

    # Set origin to the real instance, otherwise a of Spring security check will fail 
    # Same value as defined in proxy_pass 
    proxy_set_header Origin "http://testsysten:8080"; 
0

。 NGINXで基本的なSpring Security認証を使用できませんでした。 proxy_pass_header X-XSRF-TOKEN;の設定は別として、デフォルトではNGINXではヘッダーにアンダースコアが許可されておらず、CSRFトークンの名前が_csrfであるため、underscores_in_headers on;に設定する必要がありました。

だから私の最終的な設定ファイルはこのように見えた:

server { 
    underscores_in_headers on; 
    listen 80 default_server; 
    listen [::]:80 default_server ipv6only=on; 

    root /usr/share/nginx/html; 
    index index.html index.htm; 

    # Make site accessible from http://localhost/ 
    server_name localhost; 

    location/{ 
      # First attempt to serve request as file, then 
      # as directory, then fall back to displaying a 404. 
      try_files $uri $uri/ =404; 
      # Uncomment to enable naxsi on this location 
      # include /etc/nginx/naxsi.rules 
    } 
    location /example/ { 
      proxy_pass_header X-XSRF-TOKEN; 
      proxy_pass  http://localhost:8080/; 
    } 
} 
0

私はnginxのプロキシでCSRFヘッダーせずにこの問題を解決しました。

私のスタック:spring-boot、spring-security(redisセッションストア)、spring-boot-websocket with default STOMP implementation、フロントエンドを提供し、フロントエンドが消費する別のサービスにプロキシするNGINX。私はdefault configuration show in the NGINX Blog hereを使用し、ここで(歴史のためにコピー&ペースト)初めてで

http { 
    map $http_upgrade $connection_upgrade { 
     default upgrade; 
     '' close; 
    } 

    upstream websocket { 
     server 192.168.100.10:8010; 
    } 

    server { 
     listen 8020; 
     location/{ 
      proxy_pass http://websocket; 
      proxy_http_version 1.1; 
      proxy_set_header Upgrade $http_upgrade; 
      proxy_set_header Connection $connection_upgrade; 
     } 
    } 
} 

しかし、いけない仕事、まだ403禁じられました。私は非常に古典を使用していたものの、

worker_processes 1; 

events { 
    worker_connections 1024; 
} 

http { 

    include  mime.types; 
    default_type application/octet-stream; 
    sendfile  on; 
    keepalive_timeout 65; 

    server { 
     listen  30010; 
     server_name localhost; 
     client_max_body_size 10M; 

     location/{ 
      root /usr/share/nginx/html; 
      index index.html index.htm; 
     } 

     # Backend API Proxy 
     location /api { 
      proxy_pass http://192.168.0.100:30080; 
      proxy_set_header Host $http_host; 
      proxy_set_header Access-Control-Allow-Origin 192.168.0.100; 
      proxy_set_header X-Real-IP $remote_addr; 
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
      proxy_set_header X-NginX-Proxy true; 
      rewrite ^/api/?(.*) /$1 break; 
      proxy_redirect off; 
     } 

     # CDN Proxy 
     location ~ ^/cdn/(.*) { 
      proxy_pass http://192.168.0.110:9000; 
      rewrite ^/cdn/(.*) /$1 break; 
     } 

     # This is the configuration that fix the problem with WebSocket 
     # WebSocket Proxy 
     location /ws { 
      proxy_pass http://192.168.0.120:30090; 
      proxy_http_version 1.1; 
      proxy_set_header Upgrade $http_upgrade; 
      proxy_set_header Connection "upgrade"; 
      proxy_set_header Host $http_host; 
      proxy_set_header Access-Control-Allow-Origin 192.168.0.120; 
      proxy_set_header X-Real-IP $remote_addr; 
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
      proxy_set_header X-NginX-Proxy true; 
     } 

    } 

} 
1

受け入れソリューションは私のために動作しませんでした:

は、私は以下の設定でこの問題を修正(のWebSocketを修正するための本当の重要な部分 #のWebSocketプロキシです) HTTPSの設定:

server { 
    listen 443 ssl; 
    location /ws { 
     proxy_http_version 1.1; 
     proxy_set_header Upgrade $http_upgrade; 
     proxy_set_header Connection "upgrade"; 
     proxy_set_header Host $http_host; 
     proxy_pass http://127.0.0.1:8888; 
    } 
... 

問題は、春には、原点をチェックし、特にそのコードは私にトラブルを起こしたことがあります

// in org.springframework.web.util.UriComponentsBuilder.adaptFromForwardedHeaders(HttpHeaders): 
     if ((this.scheme.equals("http") && "80".equals(this.port)) || 
       (this.scheme.equals("https") && "443".equals(this.port))) { 
      this.port = null; 
     } 

このコードでは、スキームは「http」でポートは8888で、標準ポートではないため破棄されません。

ただし、ブラウザはhttps://myserver/になり、デフォルトのHTTPSであるため、443ポートは省略されています。

したがって、ポートは一致しません(空!= 8888)。起点チェックは失敗します。

どちらかあなたは春のWebSocketを原点チェックを無効にすることができます

registry.addHandler(resgisterHandler(), "/ws").setAllowedOrigins("*"); 

または(おそらくより安全な)あなたはnginxのプロキシ設定にスキームとポートを追加することができます。

proxy_set_header X-Forwarded-Proto $scheme; 
    proxy_set_header X-Forwarded-Port $server_port; 

あなたの場合興味がある場合は、それらのヘッダを読み込みます。

org.springframework.web.util.UriComponentsBuilder.adaptFromForwardedHeaders(HttpHeaders)