jersey安全和会话pipe理

有没有办法在泽西岛编程式获得会话pipe理或安全性,例如Web应用程序会话pipe理? 还是事务,会话和安全都由部署Jersey应用程序的容器处理?

会话pipe理是部署泽西的容器的范围。 在大多数生产环境中,它将部署在执行会话pipe理的容器中。

下面的代码是一个jersey资源的简单示例,它获取会话对象并将值存储在会话中,并在随后的调用中检索它们。

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

我认为会话是我们绝不应该在RESTful应用程序中使用的东西…

叶戈尔是对的。 我们不应该永远保持在传统的Web应用程序的服务器端状态。 如果要构build一个分离的面向SOA的应用程序,则不需要为REST Web服务使用任何API /框架。 如果您需要或希望在服务器端维护全局客户机 – 服务器状态,则隐式地构build我们可以描述为面向SOA的[web]应用程序,但像使用Jersey这样的[web]开发框架来构build。 无意中你正在扭曲networking服务的本质(REST或其他)。 你可以用第一个答案中的build议方式来做,但是你不能 。 最终的结果不是一个Web服务,而是一个使用Web服务工具构build的常规应用程序。

-_o

是的,这是可能的。 泽西岛文件说:

通过使用@Context注释注入JAX-RS SecurityContext实例,可以获得请求的安全性信息。 注入的安全上下文实例提供了HttpServletRequest API上可用function的等价物。 注入的安全上下文取决于实际的Jersey应用程序部署。 例如,对于部署在Servlet容器中的Jersey应用程序,Jersey SecurityContext将封装从Servlet请求中检索的安全上下文中的信息。 如果Jersey应用程序部署在Grizzly服务器上,SecurityContext将返回从Grizzly请求中检索的信息。

例:

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

要么

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

或者,如果您想通过注释来获得安全性,请查看这些文档 。

Jersey也允许你自定义SecurityContext:

SecurityContext可以通过getSecurityContext()方法直接从ContainerRequestContext中获取。 您还可以使用setSecurityContext(SecurityContext)方法将请求上下文中的默认SecurityContextreplace为自定义SecurityContext。 如果你在你的ContainerRequestFilter中设置一个自定义的SecurityContext实例,这个安全上下文实例将被用于注入JAX-RS资源类字段。 这样你可以实现一个自定义authenticationfilter,可以设置你自己的SecurityContext来使用。 为确保自定义authentication请求filter的早期执行,请使用Priorities中的常量将filter优先级设置为AUTHENTICATION。 早期执行authenticationfilter将确保所有其他filter,资源,资源方法和子资源定位器将与您的自定义SecurityContext实例一起执行。

查看关于如何使用Jersey的请求filter的示例 。 并检查我的下面的例子:

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

警告! 这是在泽西岛2.4引入的 。 Glassfish 4.0.0使用老泽西岛2.0,因此你将不得不使用这些提示升级泽西岛 (它没有certificate工作正常)。 或者更好的方法是下载Glassfish 4.0.1的每晚构build 。 但目前还不完全稳定。 我希望新版本即将发布。

更新:目前(2014-02-14)Glassfish 4.0.1每晚编译使用Jersey 2.5.1,上下文注入很好。

杰克对会议的回应是正确的。 它们是特定于您执行的容器的,尽pipeServlet规范至less为您提供了JavaEE容器之间的可移植性。

至于安全性方面,您至less有机会通过使用JaaS(Javaauthentication和授权服务)和一个servletfilter将它从JAX-RS特定代码中分离出来。 filter可用于强制执行HTTP身份validation,并在成功validation后,使用适当的Principals设置JaaS主题。 您的JAX-RS资源可以检查主题上的相应主体。 由于您控制了整个堆栈,因此您应该可以依赖资源中已通过身份validation的用户(但请testing此操作!),并且可以根据资源代码中的当前操作强制执行授权。

我解决了这个问题,让客户端添加Authorization头,并像REST方法一样testing它:

 @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 

这样就有了authentication而不需要启动一个会话。

对于Jersey安全性,您应该看看泽西OAuth支持。 当您将系统的API公开给外部用户时,OAuth非常适合。 比如像linkedin api

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

您可以使用@path将单个名称空间下的服务分组。 例如。

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

您可以在此filter类中validation您的会话。