Java 球衣安全和会话管理
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/909185/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jersey security and session management
提问by Adhir
Is there a way to get session management or security programatically in Jersey, e.g. web-application session management? Or are transactions, sessions, and security all handled by the container in which the Jersey application is deployed?
有没有办法在 Jersey 中以编程方式获得会话管理或安全性,例如 Web 应用程序会话管理?还是事务、会话和安全性都由部署 Jersey 应用程序的容器处理?
采纳答案by Hyman Cox
Session management is the purview of the container in which Jersey is deployed. In most production cases, it will be deployed within a container that performs session management.
会话管理是部署 Jersey 的容器的权限。在大多数生产情况下,它将部署在执行会话管理的容器中。
The code below is a simple example of a jersey resource that gets the session object and stores values in the session and retrieves them on subsequent calls.
下面的代码是一个 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();
}
}
回答by StevenC
Hyman's response about sessions is correct. They are specific to the container that you execute in, although the Servlet spec at least gives you portability between JavaEE containers.
Hyman关于会话的回答是正确的。它们特定于您在其中执行的容器,尽管 Servlet 规范至少为您提供了 JavaEE 容器之间的可移植性。
As for security, you at least have the opportunity to separate it from your JAX-RS specific code by employing JaaS (Java Authentication and Authorization Service) and a servlet filter. The filter can be used to enforce HTTP authentication and, on successful auth, setup the JaaS Subject with the appropriate Principals. Your JAX-RS resources can check for the appropriate Principals on the Subject. Since you control the whole stack, you should be able to rely on an authenticated user in your resources (but do test this!), and you can enforce authorization based on the current operation in the resource code.
至于安全性,您至少有机会通过使用 JaaS(Java 身份验证和授权服务)和servlet 过滤器将其与 JAX-RS 特定代码分开。过滤器可用于强制执行 HTTP 身份验证,并在身份验证成功时使用适当的主体设置 JaaS 主题。您的 JAX-RS 资源可以检查主题上的适当主体。由于您控制整个堆栈,因此您应该能够依赖资源中经过身份验证的用户(但请务必对此进行测试!),并且您可以根据资源代码中的当前操作强制执行授权。
回答by abovesun
For Jersey security you should take a look on jersey OAuth support. OAuth perfectly fits when you expose API for your system to external users. For example like the linkedin api
对于 Jersey 安全性,您应该查看 jersey OAuth 支持。当您将系统的 API 公开给外部用户时,OAuth 非常适合。例如像linkedin api
回答by MAM
I thought that sessions is something we should neveruse in RESTful applications...
我认为会话是我们永远不应该在 RESTful 应用程序中使用的东西......
Yegor is right. We shouldn't never maintain state in the server side a laconventional web application. If you want to build a decoupled SOA-oriented application you don't need to use any API/framework for REST web services. If you need, or want, to maintain the global client-server state in the server side you are implicitly building what we could describe as a SOA-oriented [web]app, but using Jersey like a [web] development framework of sorts. Inadvertently you are twisting the nature of a web service (REST or otherwise). You cando it in the way it's been suggested in the first answer, but you mustn't. The final result is not a web service, just a regular app constructed with web services' tools.
叶戈尔是对的。在服务器端,我们不应该永远保持状态一拉传统的Web应用程序。如果您想构建一个面向 SOA 的解耦应用程序,您不需要为 REST Web 服务使用任何 API/框架。如果您需要或想要在服务器端维护全局客户端 - 服务器状态,您正在隐式构建我们可以描述为面向 SOA 的 [web] 应用程序,但使用 Jersey 就像一个 [web] 开发框架。您无意中扭曲了 Web 服务(REST 或其他)的性质。您可以按照第一个答案中建议的方式进行操作,但您不能这样做。最终结果不是 Web 服务,只是使用 Web 服务工具构建的常规应用程序。
-_o
-_o
回答by Ron
I solved this problem by having the clients add the Authorization header and testing it in the REST methode like this:
我通过让客户端添加 Authorization 标头并在 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
This way there is authentication without starting a session.
这样就可以在不启动会话的情况下进行身份验证。
回答by Viacheslav Dobromyslov
Yes it's possible. Jersey documentationsays:
是的,这是可能的。泽西文件说:
Security information of a request is available by injecting a JAX-RS SecurityContext instance using @Context annotation. The injected security context instance provides the equivalent of the functionality available on HttpServletRequest API. The injected security context depends on the actual Jersey application deployment. For example, for a Jersey application deployed in a Servlet container, the Jersey SecurityContext will encapsulate information from a security context retrieved from the Servlet request. In case of a Jersey application deployed on a Grizzly server, the SecurityContext will return information retrieved from the Grizzly request.
通过使用 @Context 注释注入 JAX-RS SecurityContext 实例,可以获得请求的安全信息。注入的安全上下文实例提供了与 HttpServletRequest API 上可用的功能等效的功能。注入的安全上下文取决于实际的 Jersey 应用程序部署。例如,对于部署在 Servlet 容器中的 Jersey 应用程序,Jersey SecurityContext 将封装从 Servlet 请求中检索到的安全上下文中的信息。如果 Jersey 应用程序部署在 Grizzly 服务器上,SecurityContext 将返回从 Grizzly 请求中检索到的信息。
Example:
例子:
@Path("basket")
public ShoppingBasketResource get(@Context SecurityContext sc) {
if (sc.isUserInRole("PreferredCustomer") {
return new PreferredCustomerShoppingBasketResource();
} else {
return new ShoppingBasketResource();
}
}
or
或者
@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();
}
}
Or if you want security out of the box with annotations check these docs.
或者,如果您想要带有注释的开箱即用的安全性,请检查这些文档。
Jersey also allows you to customize the SecurityContext:
Jersey 还允许您自定义 SecurityContext:
The SecurityContext can be directly retrieved from ContainerRequestContext via getSecurityContext() method. You can also replace the default SecurityContext in a request context with a custom one using the setSecurityContext(SecurityContext) method. If you set a custom SecurityContext instance in your ContainerRequestFilter, this security context instance will be used for injection into JAX-RS resource class fields. This way you can implement a custom authentication filter that may setup your own SecurityContext to be used. To ensure the early execution of your custom authentication request filter, set the filter priority to AUTHENTICATION using constants from Priorities. An early execution of you authentication filter will ensure that all other filters, resources, resource methods and sub-resource locators will execute with your custom SecurityContext instance.
可以通过 getSecurityContext() 方法直接从 ContainerRequestContext 检索 SecurityContext。您还可以使用 setSecurityContext(SecurityContext) 方法将请求上下文中的默认 SecurityContext 替换为自定义的。如果您在 ContainerRequestFilter 中设置自定义 SecurityContext 实例,则此安全上下文实例将用于注入 JAX-RS 资源类字段。通过这种方式,您可以实现自定义身份验证过滤器,该过滤器可以设置您自己的 SecurityContext 以供使用。为确保尽早执行您的自定义身份验证请求过滤器,请使用优先级中的常量将过滤器优先级设置为 AUTHENTICATION。尽早执行您的身份验证过滤器将确保所有其他过滤器、资源、
See examples on how to use request filters with Jersey. And check my following example:
请参阅有关如何在 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;
}
});
}
}
Warning! This was introduced in Jersey 2.4. Glassfish 4.0.0 uses old Jersey 2.0 therefore you will have to upgrade Jersey using these tips(it's not proven to work well). Or the better way is to download the nightly build of Glassfish 4.0.1. but it's not completely stable at the moment. I hope the new version will be released soon.
警告!这是在 Jersey 2.4 中引入的。Glassfish 4.0.0 使用旧的 Jersey 2.0,因此您必须使用这些技巧升级 Jersey(尚未证明它运行良好)。或者更好的方法是下载Glassfish 4.0.1 的夜间版本。但目前还不是完全稳定。我希望新版本能尽快发布。
UPDATE:At the moment (2014-02-14) Glassfish 4.0.1 nightly build uses Jersey 2.5.1 and context injection works great.
更新:目前 (2014-02-14) Glassfish 4.0.1 nightly build 使用 Jersey 2.5.1 并且上下文注入效果很好。
回答by ThmHarsh
You can user @path to group the services under single name space. example .
您可以使用@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();
}
}
}
You can validate you session in this filter class.
您可以在此过滤器类中验证您的会话。