java - tutorial - Jersey seguridad y gestión de sesión
web service rest java eclipse (7)
Pensé que las sesiones es algo que nunca deberíamos usar en aplicaciones REST ...
Yegor tiene razón. Nunca debemos mantener el estado en el lado del servidor en una aplicación web convencional. Si desea compilar una aplicación orientada a SOA desacoplada, no necesita utilizar ningún API / framework para los servicios web REST. Si necesita, o desea, mantener el estado global de cliente-servidor en el lado del servidor, está construyendo implícitamente lo que podríamos describir como una aplicación [web] orientada a SOA, pero utilizando Jersey como un marco de desarrollo de desarrollo [web]. Inadvertidamente, está torciendo la naturaleza de un servicio web (REST o de otro tipo). Puede hacerlo de la manera que se sugirió en la primera respuesta, pero no debe hacerlo . El resultado final no es un servicio web, solo una aplicación regular construida con herramientas de servicios web.
-_o
¿Hay una manera de obtener la administración de sesiones o la seguridad programáticamente en Jersey, por ejemplo, la administración de sesiones de aplicaciones web? ¿O son las transacciones, las sesiones y la seguridad todas manejadas por el contenedor en el que se implementa la aplicación Jersey?
La gestión de sesiones es el ámbito del contenedor en el que se implementa Jersey. En la mayoría de los casos de producción, se implementará dentro de un contenedor que realiza la administración de sesiones.
El código a continuación es un ejemplo simple de un recurso de jersey que obtiene el objeto de la sesión y almacena los valores en la sesión y los recupera en las llamadas posteriores.
@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();
}
}
La respuesta de Jack sobre las sesiones es correcta. Son específicos del contenedor en el que se ejecuta, aunque la especificación del Servlet al menos le brinda portabilidad entre los contenedores de JavaEE.
En cuanto a la seguridad, al menos tiene la oportunidad de separarlo de su código específico de JAX-RS empleando JaaS (Servicio de Autorización y Autenticación de Java) y un filtro de servlet . El filtro se puede usar para imponer la autenticación HTTP y, en una autenticación exitosa, configurar el Asunto JaaS con los Principios apropiados. Sus recursos de JAX-RS pueden verificar los Principios apropiados sobre el tema. Ya que controla toda la pila, debería poder confiar en un usuario autenticado en sus recursos (¡pero pruebe esto!), Y puede aplicar la autorización en función de la operación actual en el código de recurso.
Para la seguridad de Jersey, debería echar un vistazo a la asistencia de jersey OAuth. OAuth se ajusta perfectamente cuando expone la API de su sistema a usuarios externos. Por ejemplo, como el api linkedin
Puede usar @path para agrupar los servicios en un espacio de nombre único. ejemplo
@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();
}
}
}
Puede validar su sesión en esta clase de filtro.
Resolví este problema haciendo que los clientes agregaran el encabezado de Autorización y lo probaran en el método REST de la siguiente manera:
@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
De esta manera hay autenticación sin iniciar una sesión.
Si es posible. La documentation Jersey dice:
La información de seguridad de una solicitud está disponible inyectando una instancia de JAX-RS SecurityContext usando la anotación @Context. La instancia de contexto de seguridad inyectada proporciona el equivalente de la funcionalidad disponible en la API HttpServletRequest. El contexto de seguridad inyectado depende de la implementación real de la aplicación Jersey. Por ejemplo, para una aplicación Jersey implementada en un contenedor Servlet, Jersey SecurityContext encapsulará la información de un contexto de seguridad recuperado de la solicitud de Servlet. En el caso de una aplicación de Jersey implementada en un servidor Grizzly, SecurityContext devolverá la información recuperada de la solicitud Grizzly.
Ejemplo:
@Path("basket")
public ShoppingBasketResource get(@Context SecurityContext sc) {
if (sc.isUserInRole("PreferredCustomer") {
return new PreferredCustomerShoppingBasketResource();
} else {
return new ShoppingBasketResource();
}
}
o
@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();
}
}
O si desea seguridad fuera de la caja con anotaciones, verifique estos documentos .
Jersey también te permite personalizar el SecurityContext:
El SecurityContext se puede recuperar directamente de ContainerRequestContext a través del método getSecurityContext (). También puede reemplazar el SecurityContext predeterminado en un contexto de solicitud con uno personalizado usando el método setSecurityContext (SecurityContext). Si configura una instancia personalizada de SecurityContext en su ContainerRequestFilter, esta instancia de contexto de seguridad se utilizará para la inyección en los campos de clase de recursos JAX-RS. De esta manera, puede implementar un filtro de autenticación personalizado que puede configurar su propio SecurityContext para ser utilizado. Para garantizar la ejecución temprana de su filtro de solicitud de autenticación personalizado, establezca la prioridad del filtro en AUTENTICACIÓN utilizando constantes de Prioridades. Una ejecución temprana de su filtro de autenticación asegurará que todos los demás filtros, recursos, métodos de recursos y localizadores de sub-recursos se ejecutarán con su instancia personalizada de SecurityContext.
Vea ejemplos sobre cómo usar los filtros de solicitud con Jersey . Y revisa mi siguiente ejemplo:
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;
}
});
}
}
¡Advertencia! Esto fue introducido en Jersey 2.4 . Glassfish 4.0.0 usa el viejo Jersey 2.0, por lo tanto, tendrá que actualizarlo con estos consejos (no se ha comprobado que funcione bien). O la mejor manera es descargar la compilación nocturna de Glassfish 4.0.1 . Pero no es completamente estable en este momento. Espero que la nueva versión sea lanzada pronto.
ACTUALIZACIÓN: En este momento (2014-02-14), la versión nocturna de Glassfish 4.0.1 utiliza Jersey 2.5.1 y la inyección de contexto funciona muy bien.