42

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

4

7 回答 7

68

会话管理是部署 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();


    }
}
于 2009-05-28T17:06:20.077 回答
23

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

叶戈尔是对的。我们不应该像传统的Web 应用程序那样在服务器端维护状态。如果您想构建一个解耦的面向 SOA 的应用程序,您不需要为 REST Web 服务使用任何 API/框架。如果您需要或想要在服务器端维护全局客户端-服务器状态,那么您正在隐式构建我们可以描述为面向 SOA 的 [web] 应用程序,但使用 Jersey 就像是一种 [web] 开发框架。您无意中扭曲了 Web 服务(REST 或其他)的性质。您可以按照第一个答案中建议的方式进行操作,但您不能这样做。最终的结果不是一个 Web 服务,只是一个使用 Web 服务工具构建的常规应用程序。

-_o

于 2011-10-13T09:45:10.263 回答
16

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

可以通过使用 @Context 注释注入 JAX-RS SecurityContext 实例来获得请求的安全信息。注入的安全上下文实例提供了与 HttpServletRequest API 上可用的功能等效的功能。注入的安全上下文取决于实际的 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) 方法将请求上下文中的默认 SecurityContext 替换为自定义的。如果您在 ContainerRequestFilter 中设置自定义 SecurityContext 实例,则此安全上下文实例将用于注入 JAX-RS 资源类字段。通过这种方式,您可以实现自定义身份验证过滤器,该过滤器可以设置您自己的要使用的 SecurityContext。要确保尽早执行您的自定义身份验证请求过滤器,请使用 Priorities 中的常量将过滤器优先级设置为 AUTHENTICATION。尽早执行您的身份验证过滤器将确保所有其他过滤器、资源、

请参阅有关如何将请求过滤器与 Jersey 一起使用的示例。并检查我的以下示例:

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

警告!这是在 Jersey 2.4 中引入的。Glassfish 4.0.0 使用旧的 Jersey 2.0,因此您必须使用这些技巧来升级 Jersey(尚未证明效果很好)。或者更好的方法是下载Glassfish 4.0.1 的夜间版本。但目前还不是完全稳定。我希望新版本能尽快发布。

更新: 目前 (2014-02-14) Glassfish 4.0.1 nightly build 使用 Jersey 2.5.1 并且上下文注入效果很好。

于 2013-11-05T12:34:02.717 回答
6

杰克关于会话的回答是正确的。它们特定于您在其中执行的容器,尽管 Servlet 规范至少为您提供了 JavaEE 容器之间的可移植性。

至于安全性,您至少有机会通过使用 JaaS(Java 身份验证和授权服务)和servlet 过滤器将其与您的 JAX-RS 特定代码分开。该过滤器可用于强制执行 HTTP 身份验证,并且在成功的身份验证后,使用适当的 Principal 设置 JaaS 主题。您的 JAX-RS 资源可以检查主题上的适当主体。由于您控制整个堆栈,因此您应该能够依赖资源中经过身份验证的用户(但一定要对此进行测试!),并且您可以根据资源代码中的当前操作强制执行授权。

于 2009-06-13T05:31:55.920 回答
4

我通过让客户端添加授权标头并在 REST 方法中对其进行测试来解决此问题,如下所示:

@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

这样就可以在不启动会话的情况下进行身份验证。

于 2011-11-07T16:11:48.257 回答
3

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

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

于 2010-05-07T09:22:08.423 回答
2

您可以使用 @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();
                       }
          }
    }

您可以在此过滤器类中验证您的会话。

于 2014-09-17T08:40:27.493 回答