[英]jersey security and session management
有没有办法在Jersey中以编程方式获得会话管理或安全性,例如Web应用程序会话管理? 或者,事务,会话和安全性是否都由部署Jersey应用程序的容器处理?
会话管理是部署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应用程序,我们不应该永远保持状态。 如果要构建一个分离的面向SOA的应用程序,则不需要使用任何API /框架来进行REST Web服务。 如果您需要或希望在服务器端维护全局客户端 - 服务器状态,那么您将隐式构建我们可以描述为面向SOA的[Web]应用程序,但是使用Jersey就像[web]开发框架一样。 无意中,您正在扭曲Web服务(REST或其他)的本质。 您可以按照第一个答案中建议的方式进行,但您不能这样做 。 最终结果不是Web服务,只是使用Web服务工具构建的常规应用程序。
-_o
是的,这是可能的。 泽西文件说:
通过使用@Context注释注入JAX-RS SecurityContext实例,可以获得请求的安全信息。 注入的安全上下文实例提供HttpServletRequest API上可用功能的等效项。 注入的安全上下文取决于实际的Jersey应用程序部署。 例如,对于部署在Servlet容器中的Jersey应用程序,Jersey SecurityContext将封装来自从Servlet请求检索的安全上下文的信息。 如果在Grizzly服务器上部署了Jersey应用程序,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:
可以通过getSecurityContext()方法从ContainerRequestContext直接检索SecurityContext。 您还可以使用setSecurityContext(SecurityContext)方法将请求上下文中的默认SecurityContext替换为自定义SecurityContext。 如果在ContainerRequestFilter中设置自定义SecurityContext实例,则此安全上下文实例将用于注入JAX-RS资源类字段。 这样,您就可以实现自定义身份验证筛选器,该筛选器可以设置您自己的SecurityContext以供使用。 要确保提前执行自定义身份验证请求筛选器,请使用“优先级”中的常量将筛选器优先级设置为AUTHENTICATION。 早期执行身份验证筛选器将确保所有其他筛选器,资源,资源方法和子资源定位器将与您的自定义SecurityContext实例一起执行。
请参阅有关如何使用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;
}
});
}
}
警告! 这是在泽西岛2.4中引入的 。 Glassfish 4.0.0使用旧的Jersey 2.0,因此你必须使用这些技巧升级泽西岛 (它没有被证明效果很好)。 或者更好的方法是下载Glassfish 4.0.1的每晚版本 。 但目前还不完全稳定。 我希望新版本即将发布。
更新:目前(2014-02-14)Glassfish 4.0.1每晚构建使用Jersey 2.5.1并且上下文注入效果很好。
杰克对会议的回应是正确的。 它们特定于您执行的容器,尽管Servlet规范至少为您提供了JavaEE容器之间的可移植性。
至于安全性,您至少有机会通过使用JaaS(Java身份验证和授权服务)和servlet过滤器将其与JAX-RS特定代码分开。 过滤器可用于强制执行HTTP身份验证,并且在成功验证后,使用适当的主体设置JaaS主题。 您的JAX-RS资源可以检查主题上的相应主体。 由于您控制整个堆栈,您应该能够依赖资源中经过身份验证的用户(但要对此进行测试!),并且您可以根据资源代码中的当前操作强制执行授权。
我通过让客户端添加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
这样,无需启动会话即可进行身份验证。
对于Jersey安全,你应该看看球衣OAuth支持。 当您将系统的API公开给外部用户时,OAuth非常适合。 例如像linkedin api
您可以使用@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();
}
}
}
您可以在此过滤器类中验证您的会话。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.