2015-12-07 16 views
5

Tôi đang sử dụng Nginx làm proxy ngược của ứng dụng khởi động Spring. Tôi cũng sử dụng Websockets với sockjs và stomp messages.Xác thực Web proxy của Nginx Reverse Proxy - HTTP 403

Đây là cấu hình ngữ cảnh.

<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> 

Đây là mã khách hàng:

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

Tôi cũng bạn Xuân An để bảo vệ một số nội dung.

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

} 

Mọi thứ hoạt động tốt, mong đợi khi tôi chạy ứng dụng này sau proxy ngược Nginx. Đây là cấu hình ngược lại:

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; 

Kết nối luôn không thành công với mã HTTP 403.

Tôi đang sử dụng phiên bản 1.9.7.

Bạn có ý tưởng nào không, tại sao khách hàng không được xác thực?

Tôi biết các câu hỏi tương tự, như this one nhưng các giải pháp không hoạt động chút nào.

Cập nhật

Tôi đã quản lý để chạy ứng dụng qua HTTP. Tôi cần phải chuyển mã thông báo CSRF trong cấu hình Nginx. Cấu hình mới là:

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; 

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

    # WebSocket support (nginx 1.4) 
    proxy_http_version 1.1; 

Chỉ thiếu bị chuyển hướng qua HTTPS. Trong các bản ghi mùa xuân là thấy sau entry:

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

Có vẻ như Nginx Proxy cần phải viết lại để các cổng bên phải.

Trả lời

7

Tôi đã tự khắc phục sự cố. Về cơ bản, Nginx cần phải vượt qua một số giá trị tiêu đề bổ sung nếu bạn muốn sử dụng Websocket và Spring Security. Bạn cần thêm các dòng sau vào phần location trong cấu hình Nginx của mình:

# 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

Tôi đã gặp phải sự cố tương tự. Tôi không thể sử dụng xác thực Spring Security cơ bản với NGINX. Ngoài việc đặt proxy_pass_header X-XSRF-TOKEN;, tôi cũng phải đặt underscores_in_headers on;, vì NGINX theo mặc định không cho phép tiêu đề có dấu gạch dưới và mã thông báo CSRF có tên là _csrf.

Vì vậy, tập tin cấu hình cuối cùng của tôi trông như thế này:

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

tôi giải quyết vấn đề này mà không CSRF tiêu đề trong nginx proxy.

Ngăn xếp của tôi: spring-boot, spring-security (với redis session store), spring-boot-websocket with default STOMP implementation, NGINX để phục vụ giao diện người dùng và được ủy quyền cho các dịch vụ khác mà giao diện người dùng tiêu thụ.

Trong lần đầu tiên tôi sử dụng default configuration show in the NGINX Blog here và tại đây (sao chép và dán cho lịch sử):

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

Nhưng không làm việc, vẫn còn 403 Forbidden.

Tôi cố định vấn đề này với các cấu hình dưới đây (phần quan trọng thực để sửa chữa WebSocket là # WebSocket Proxy):

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

Các giải pháp chấp nhận không làm việc cho tôi mặc dù tôi đã sử dụng một rất cổ điển cấu hình 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; 
    } 
... 

vấn đề là mùa xuân sẽ kiểm tra nguồn gốc và đặc biệt là mã mà đã gây cho tôi rắc rối:

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

Trong mã đó, lược đồ là 'http' và cổng là 8888, không bị hủy vì nó không phải là cổng chuẩn.

Tuy nhiên, trình duyệt truy cập https://myserver/ và cổng 443 bị bỏ qua vì đây là cổng mặc định HTTPS.

Do đó các cổng không khớp (trống! = 8888) và kiểm tra xuất xứ không thành công.

Hoặc bạn có thể tắt kiểm tra nguồn gốc trong WebSockets mùa xuân:

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

hoặc (lẽ an toàn hơn), bạn có thể thêm các chương trình và cổng để cấu hình proxy Nginx:

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

Nếu bạn quan tâm, các tiêu đề đó được đọc trong

org.springframework.web.util.UriComponentsBuilder.adaptFromForwardedHeaders(HttpHeaders) 
Các vấn đề liên quan