2013-05-03 21 views
8

Tôi không chắc vấn đề này có liên quan đến công nghệ hay hiểu biết của tôi về công nghệ hay không.Không được phép truy cập nguồn gốc Access-Control-Allow-Origin - cách bật CORS bằng cách sử dụng ngăn xếp web rất đơn giản và guice

Tôi có một ứng dụng html5 được viết bằng javascript và html được lưu trữ trên máy chủ apache 2.2.

Tôi có một ứng dụng java được viết bằng java sử dụng cầu cảng, guice, jackson, jersey lưu trữ một dịch vụ REST đơn giản.

Cả hai ứng dụng chạy trên cùng một hộp, một trên cổng 80 (ứng dụng thuần túy html5 lưu trữ trên apache), người kia trên 8080 (ứng dụng java tinh khiết được lưu trữ trên cầu cảng/Guice)

Tôi tin rằng câu trả lời là trong tiêu đề im gửi lại. Tiêu đề CORS cho trình duyệt biết bạn cho phép các ứng dụng bên ngoài truy cập api của bạn. Tôi không thể tìm ra cách để cấu hình Jetty của tôi, máy chủ Guice để trả về các tiêu đề CORS đúng.

Tôi đang sử dụng máy chủ Jetty được nhúng nên tôi không có tệp web.xml để thêm tiêu đề.

Nó cũng có thể liên quan đến cách máy chủ ứng dụng HTML5 (trong trường hợp này là apache 2.2) đang phục vụ ứng dụng.

Các tập tin httpd.conf apache có mục:

LoadModule headers_module modules/mod_headers.so 

<IFModule mod_headers> 
    Header add Access-Control-Allow-Origin "*" 
    Header add Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE, HEAD 
    Header add Access-Control-Allow-Headers: X-PINGOTHER 
    Header add Access-Control-Max-Age: 1728000 
</IfModule> 

trong cấu hình Guice servlet của tôi, tôi có như sau:

public class RestModule extends ServletModule{ 

    @Override 
    protected void configureServlets() { 
     bind(QuestbookService.class); 

     // hook Jersey into Guice Servlet 
     bind(GuiceContainer.class); 

     // hook Jackson into Jersey as the POJO <-> JSON mapper 
     bind(JacksonJsonProvider.class).in(Scopes.SINGLETON); 

     Map<String, String> guiceContainerConfig = new HashMap<String, String>(); 
     guiceContainerConfig.put(ResourceConfig.PROPERTY_RESOURCE_FILTER_FACTORIES, 
      HttpStatusCodeMetricResourceFilterFactory.class.getCanonicalName()); 
     serve("/*").with(GuiceContainer.class, guiceContainerConfig); 
    } 
} 

Tôi nghĩ rằng vấn đề là ở cấu hình Guice của tôi kể từ khi tôi don không có nơi để đặt tiêu đề phản hồi.

Tôi đang sử dụng máy chủ cầu nối được nhúng và do đó tôi đã tìm chế độ dev sẽ bỏ qua toàn bộ kiểm tra, nhưng tôi có thể sai.

Cảm ơn bạn đã được tư vấn.

+0

thể trùng lặp của [Tại sao tôi lại thấy một "nguồn gốc không được phép bởi Access-Control-Allow-Origin" lỗi ở đây?] (http://stackoverflow.com/questions/9310112/why-am-i-seeing-an-origin-is-not-allowed-by-access-control-allow-origin-error) – Barmar

+0

Câu hỏi của tôi là phía máy chủ, ví dụ giao dịch với phía máy khách. Thư viện phía khách hàng đã chăm sóc những sự không nhất quán này. Đây là một vấn đề dựa trên máy chủ. – AnthonyJClink

+0

Được thêm vào, kể từ khi sử dụng một máy chủ jetty nhúng với guice. Tôi không chắc chắn làm thế nào để cấu hình mà không có web.xml ... Tôi biết nó thiếu một sự hiểu biết về các công nghệ. nhưng tôi cảm thấy rằng công nghệ ngăn xếp trong câu hỏi này là đủ khác nhau từ các bản sao có thể có mà nó đảm bảo sự chú ý của riêng mình vì nó liên quan đến một chồng công nghệ rất khác nhau. – AnthonyJClink

Trả lời

9

Làm theo các yêu cầu cụ thể của đơn đăng ký của tôi. Máy chủ cần được phân tách hoàn toàn riêng biệt với máy khách. Máy khách sẽ có thể kết nối với máy chủ truyền thông thông qua bất kỳ phương thức nào có thể.

Kể từ khi triển khai đầu tiên của ứng dụng này sẽ được REST điều khiển, tôi cần để có thể chấp nhận phần còn lại từ bất cứ nơi nào.

Ngoài ra, tôi muốn cấu hình hoàn toàn không có xml, vì vậy tôi sử dụng Guice với một máy chủ Jetty được nhúng. Vì tôi không có tệp web.xml, tôi không thể tìm ra cách đặt tiêu đề để cho phép CORS.

Sau nhiều thử và sai, và đọc tài liệu guice, tôi đã tìm cách thêm tiêu đề CORS vào phản hồi rời khỏi máy chủ.

Lớp Guice ServletModule cho phép bạn thêm bộ lọc vào ngữ cảnh servlet của bạn. Điều này cho phép tôi có tất cả các yêu cầu đi qua một servlet đã cho.

Vì tôi đang cố gắng xây dựng một ứng dụng còn lại đáp ứng các yêu cầu của CORS, tôi cần một bộ lọc để thêm tiêu đề cors vào phản hồi của bất kỳ yêu cầu nào. Ngay bây giờ, nó phản hồi tất cả các yêu cầu, nhưng cuối cùng tôi sẽ chỉ trả lời nếu lớp dịch vụ đáp ứng với một mã phản hồi 200 - 300.

Vì vậy, để kích hoạt tính năng CORS trong máy chủ sử dụng tôi Guice nhúng tôi đã xây dựng một bộ lọc mà trông như thế này:

@Singleton 
public class CorsFilter implements Filter{ 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, 
    FilterChain filterChain) throws IOException, ServletException { 

     if(response instanceof HttpServletResponse){ 
     HttpServletResponse alteredResponse = ((HttpServletResponse)response); 
     addCorsHeader(alteredResponse); 
    } 

    filterChain.doFilter(request, response); 
    } 

    private void addCorsHeader(HttpServletResponse response){ 
     //TODO: externalize the Allow-Origin 
     response.addHeader("Access-Control-Allow-Origin", "*"); 
     response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, HEAD"); 
     response.addHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept"); 
     response.addHeader("Access-Control-Max-Age", "1728000"); 
    } 

    @Override 
    public void destroy() {} 

    @Override 
    public void init(FilterConfig filterConfig)throws ServletException{} 
} 

Guice cung cấp một lớp trừu tượng cho phép bạn cấu hình các Guice Servlet.

mô-đun

Cấu hình trông như thế này:

public class RestModule extends ServletModule{ 

    @Override 
    protected void configureServlets() { 
     bind(MyServiceClass.class); 

     // hook Jersey into Guice Servlet 
     bind(GuiceContainer.class); 

     // hook Jackson into Jersey as the POJO <-> JSON mapper 
     bind(JacksonJsonProvider.class).in(Scopes.SINGLETON); 

     Map<String, String> guiceContainerConfig = new HashMap<String, String>(); 

     serve("/*").with(GuiceContainer.class, guiceContainerConfig); 

     filter("/*").through(CorsFilter.class); 
    } 
} 

Bây giờ Guice sẽ thêm CORS tiêu đề cho tất cả các câu trả lời. Cho phép ứng dụng HTML 5 thuần túy của tôi nói chuyện với nó, bất kể nó đang được phục vụ ở đâu.

4

Chỉ cần đặt một dòng trong tập tin mã của bạn

Response.AddHeader ("Access-Control-Allow-Origin", "*");

Thay thế * với http://www.yoursite.com của bạn nếu bạn muốn cho phép chỉ cho tên miền cụ thể

+0

Tôi đã giải quyết vấn đề này bằng bộ lọc áo – AnthonyJClink