2009-05-26 32 views
41

Có cách nào để quản lý phiên hoặc bảo mật theo chương trình ở Jersey hay không, ví dụ: quản lý phiên ứng dụng web? Hoặc là các giao dịch, phiên và bảo mật đều được xử lý bởi vùng chứa trong đó ứng dụng Jersey được triển khai?bảo mật và quản lý phiên làm việc của áo

+0

Tôi vừa mới bắt đầu điều tra điều này. Tôi sẽ trả lời lại nếu tôi tìm thấy bất cứ điều gì –

Trả lời

68

Quản lý phiên là bản xem trước của vùng chứa trong đó Jersey được triển khai. Trong hầu hết các trường hợp sản xuất, nó sẽ được triển khai trong một vùng chứa thực hiện quản lý phiên.

Đoạn mã dưới đây là ví dụ đơn giản về tài nguyên jersey nhận đối tượng phiên và lưu trữ các giá trị trong phiên và truy xuất chúng trong các cuộc gọi tiếp theo.

@Path("/helloworld") 
public class HelloWorld { 

    @GET 
    @Produces("text/plain") 
    public String hello(@Context HttpServletRequest req) { 

     HttpSession session= req.getSession(true); 
     Object foo = session.getAttribute("foo"); 
     if (foo!=null) { 
      System.out.println(foo.toString()); 
     } else { 
      foo = "bar"; 
      session.setAttribute("foo", "bar"); 
     } 
     return foo.toString(); 


    } 
} 
+0

Cảm ơn Jack, tôi cần điều này vì chúng tôi phải thực hiện một số loại kiểm soát truy cập trên các dịch vụ web JAX-RS .. bất kỳ trợ giúp nào cũng sẽ được đánh giá cao .. Cảm ơn trước , Adhir – Adhir

+0

@ Jack Cox: Tôi đã đăng câu hỏi có liên quan ở đây: http://stackoverflow.com/questions/9676588/how-can-you-authenticate-using-the-jersey-client-against-a-jaas- enabled-web-serv Có lẽ bạn sẽ biết cách thực hiện điều này ở phía máy khách (với máy khách)? – carlspring

+0

@Jack Cox, nếu tôi có đơn đăng ký với 1000 người dùng đăng nhập vào cùng một lúc và mỗi người đặt 'session.setAttribute (" username ", username)'. Liệu Java có hiểu rằng có 1000 phiên khác nhau mỗi phiên với một biến có tên 'tên người dùng' với một giá trị khác với các giá trị khác? – kasavbere

6

Phản hồi của Jack về phiên là chính xác. Chúng đặc trưng cho vùng chứa mà bạn thực thi, mặc dù đặc tả Servlet ít nhất cung cấp cho bạn khả năng di chuyển giữa các thùng chứa JavaEE.

Vì lý do bảo mật, ít nhất bạn cũng có cơ hội tách nó khỏi mã cụ thể JAX-RS của bạn bằng cách sử dụng JaaS (Java Authentication and Authorization Service) và servlet filter. Bộ lọc có thể được sử dụng để thực thi xác thực HTTP và, trên auth thành công, hãy thiết lập JaaS Subject với các Principals thích hợp. Tài nguyên JAX-RS của bạn có thể kiểm tra các Hiệu trưởng phù hợp về Chủ đề. Vì bạn kiểm soát toàn bộ ngăn xếp, bạn sẽ có thể dựa vào người dùng được xác thực trong tài nguyên của mình (nhưng hãy thử nghiệm điều này!) Và bạn có thể thực thi ủy quyền dựa trên hoạt động hiện tại trong mã tài nguyên.

+1

+1 Âm thanh như một ý tưởng hay. Làm thế nào chính xác bạn có thể làm cho nó hoạt động trên Grizzly? Tôi mở một câu hỏi mới. http://stackoverflow.com/questions/1682061/using-jaas-with-jersey-on-grizzly – User1

3

Để bảo mật Jersey, bạn nên xem xét hỗ trợ OAuth cho jersey. OAuth hoàn toàn phù hợp khi bạn hiển thị API cho hệ thống của mình cho người dùng bên ngoài. Ví dụ như linkedin api

http://wikis.oracle.com/display/Jersey/OAuth

+0

Vui lòng sửa liên kết – bekce

23

tôi nghĩ rằng phiên là một cái gì đó chúng ta nên bao giờ sử dụng trong các ứng dụng RESTful ...

Yegor vậy là hợp lý. Chúng tôi không bao giờ nên duy trì trạng thái ở phía máy chủ a la ứng dụng web thông thường. Nếu bạn muốn xây dựng một ứng dụng định hướng SOA tách rời, bạn không cần sử dụng bất kỳ API/khung công tác nào cho các dịch vụ web REST. Nếu bạn cần, hoặc muốn, để duy trì trạng thái máy khách-toàn cầu ở phía máy chủ, bạn ngầm xây dựng những gì chúng ta có thể mô tả như một ứng dụng SOA [web], nhưng sử dụng Jersey như một khung công tác phát triển web. Vô tình bạn đang xoắn bản chất của một dịch vụ web (REST hay cách khác). Bạn có thể thực hiện theo cách được đề xuất trong câu trả lời đầu tiên, nhưng bạn không được. Kết quả cuối cùng không phải là một dịch vụ web, chỉ là một ứng dụng thông thường được xây dựng với các công cụ của các dịch vụ web.

-_o

+2

Điều đó không phải lúc nào cũng đúng. Nếu phiên được sử dụng như một phương tiện lưu trữ bộ nhớ đệm thì người ta có thể lập luận rằng nó được sử dụng để cải thiện hiệu suất. Bạn vẫn có thể viết một ứng dụng không trạng thái, chỉ với một phiên làm cơ chế lưu bộ nhớ đệm. – Vladimir

+0

các trang web như các phiên sử dụng facebook trên các dịch vụ web để chạy các ứng dụng web. Nó vốn không sai. Bạn cũng có thể muốn người dùng được xác thực để sử dụng dịch vụ web trong trường hợp bạn không muốn chuyển thông tin đăng nhập mỗi lần. – DiamondDrake

4

tôi giải quyết vấn đề này bằng cách cho khách hàng thêm tiêu đề Authorization và thử nghiệm nó trong tole REST của như thế này:

@GET 
@PRODUCES(MediaType.APPLICATION_JSON) 
public String returnClients(@Context HTTPServletRequest request(
    String auth = request.getHeader("Authorization"); 
    Account acc = null; 
    if (auth!=null) { 
     Account acc = Utils.LoginAccount(auth); 
    } 
    if (acc == null) 
    // not logged in, handle it gracefully 

này cách có chứng thực mà không bắt đầu một phiên làm việc.

+1

NB: Điều này hoàn toàn không an toàn trừ khi bạn đang buộc kết nối HTTPS, trong trường hợp đó bạn cũng có thể sử dụng dropwizard-auth. – Lambart

15

Có thể.Jersey documentation nói:

Thông tin bảo mật của yêu cầu có sẵn bằng cách chèn một trường hợp JAX-RS SecurityContext bằng @Context annotation. Ví dụ ngữ cảnh bảo mật được tiêm được cung cấp tương đương với chức năng có sẵn trên API HttpServletRequest. Ngữ cảnh bảo mật được tiêm phụ thuộc vào việc triển khai ứng dụng Jersey thực tế. Ví dụ: đối với một ứng dụng Jersey được triển khai trong vùng chứa Servlet, Jersey SecurityContext sẽ đóng gói thông tin từ ngữ cảnh bảo mật được truy lục từ yêu cầu Servlet. Trong trường hợp ứng dụng Jersey được triển khai trên máy chủ Grizzly, SecurityContext sẽ trả lại thông tin được truy lục từ yêu cầu Grizzly.

Ví dụ:

@Path("basket") 
public ShoppingBasketResource get(@Context SecurityContext sc) { 
    if (sc.isUserInRole("PreferredCustomer") { 
     return new PreferredCustomerShoppingBasketResource(); 
    } else { 
     return new ShoppingBasketResource(); 
    } 
} 

hoặc

@Path("resource") 
@Singleton 
public static class MyResource { 
    // Jersey will inject proxy of Security Context 
    @Context 
    SecurityContext securityContext; 

    @GET 
    public String getUserPrincipal() { 
     return securityContext.getUserPrincipal().getName(); 
    } 
} 

Hoặc nếu bạn muốn bảo mật ra khỏi hộp với các chú thích kiểm tra these docs.

Jersey cũng cho phép bạn tùy chỉnh SecurityContext:

Các SecurityContext có thể được lấy trực tiếp từ ContainerRequestContext qua getSecurityContext() phương pháp. Bạn cũng có thể thay thế SecurityContext mặc định trong ngữ cảnh yêu cầu bằng một tuỳ chỉnh một bằng cách sử dụng phương thức setSecurityContext (SecurityContext). Nếu bạn đặt phiên bản SecurityContext tùy chỉnh trong ContainerRequestFilter của mình, trường hợp ngữ cảnh bảo mật này sẽ được sử dụng để tiêm vào các trường lớp tài nguyên JAX-RS . Bằng cách này, bạn có thể triển khai bộ lọc xác thực tùy chỉnh có thể thiết lập SecurityContext của riêng bạn thành được sử dụng. Để đảm bảo thực hiện sớm bộ lọc yêu cầu xác thực tùy chỉnh , hãy đặt mức độ ưu tiên bộ lọc thành AUTHENTICATION bằng cách sử dụng hằng số từ Mức độ ưu tiên. Việc thực hiện sớm xác thực bạn bộ lọc sẽ đảm bảo rằng tất cả các bộ lọc, tài nguyên, phương pháp tài nguyên khác và trình định vị tài nguyên phụ sẽ thực thi với cá thể tùy chỉnh bảo mật tùy chỉnh của bạn.

Xem examples on how to use request filters with Jersey. Và kiểm tra ví dụ sau:

import javax.annotation.Priority; 
import javax.ws.rs.Priorities; 

@Provider 
@Priority(Priorities.AUTHENTICATION) 
public class AuthRequestFilter implements ContainerRequestFilter { 
    @Context 
    HttpServletRequest webRequest; 

    @Override 
    public void filter(ContainerRequestContext requestContext) throws IOException { 
     final HttpSession session = webRequest.getSession(); 

     requestContext.setSecurityContext(new SecurityContext() { 
      @Override 
      public Principal getUserPrincipal() { 
       return new PrincipalImpl((String)session.getAttribute("USER_NAME")); 
      } 

      @Override 
      public boolean isUserInRole(String s) { 
       return false; 
      } 

      @Override 
      public boolean isSecure() { 
       return false; 
      } 

      @Override 
      public String getAuthenticationScheme() { 
       return null; 
      } 
     }); 
    } 
} 

Cảnh báo! This was introduced in Jersey 2.4. Glassfish 4.0.0 sử dụng phiên bản Jersey 2.0 cũ do đó bạn sẽ phải upgrade Jersey using these tips (nó không được chứng minh là hoạt động tốt). Hoặc cách tốt hơn là tải xuống the nightly build of Glassfish 4.0.1. nhưng nó không hoàn toàn ổn định vào lúc này. Tôi hy vọng phiên bản mới sẽ sớm được phát hành.

CẬP NHẬT: Hiện tại (2014-02-14) Glassfish 4.0.1 xây dựng hàng đêm sử dụng Jersey 2.5.1 và ngữ cảnh hoạt động tốt.

+1

Câu trả lời hay! cảm ơn –

2

Bạn có thể sử dụng @path để nhóm các dịch vụ theo không gian tên duy nhất. ví dụ.

@Path("/helloworld") 
public class HelloWorld { 

    @GET 
    @Produces("text/plain") 
    public String hello() { 


     return ""; 


    } 
}
Instead of @Path("/helloworld") use 
@Path("admin/helloworld") to expose you class as rest and bind filter on "admin/" 
in web.xml as below. 

<servlet> 
      <servlet-name>jersey-serlvet</servlet-name> 
      <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> 
      <init-param> 
       <param-name>com.sun.jersey.config.property.packages</param-name> 
       <param-value>/</param-value> 
      </init-param> 
      <load-on-startup>1</load-on-startup> 
     </servlet> 
     <servlet-mapping> 
      <servlet-name>jersey-serlvet</servlet-name> 
      <url-pattern>/rest/*</url-pattern> 
     </servlet-mapping> 
     <filter> 
      <filter-name>myfilter</filter-name> 
      <filter-class>com.Filterclass</filter-class> 
     </filter> 
     <filter-mapping> 
      <filter-name>myfilter</filter-name> 
      <url-pattern>/rest/admin/*</url-pattern> 
     </filter-mapping> 

    public class Filterclass implements Filter { 
     public void doFilter(ServletRequest request, ServletResponse response, 
       FilterChain chain) 
       throws IOException, ServletException { 
        try{ 
         chain.doFilter(request, response); 
        }catch(Exception e){ 
        e.printStackTrace(); 
         } 
      } 
    }

Bạn có thể xác nhận bạn session trong lớp bộ lọc này.

Các vấn đề liên quan