6

Estoy intentando agregar autenticación BASIC a mi servicio web RESTful. Actualmente tengo la autenticación BASIC para un servidor Apache Tomcat 6.0, pero necesito implementar mi servicio web en una versión del servidor de aplicaciones WebSphere. 6.1 también y tengo problemas para ejecutar la autenticación BASIC en WebSphere.¿Existe una manera independiente del servidor de implementar la autenticación básica?

¿Hay alguna forma en Java para verificar los encabezados de autenticación de una solicitud HTTP y si el nombre de usuario/contraseña proporcionada (en codificación Base64) no coincide con una cuenta conocida, obliga al usuario a ingresar un nuevo nombre de usuario/contraseña?

He intentado implementar Spring Security, pero como mi proyecto se realizó completamente sin Spring, ha sido un gran problema intentar que funcione, y estoy intentando encontrar una solución simple a mi problema bastante simple.

Las tecnologías que utilizo actualmente incluyen: Java, Jersey/JAX-RS, Eclipse con el plugin Maven.

+0

http://publib.boulder.ibm.com/infocenter/wasinfo/v6r1/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/twbs_auwschta.html ? –

+0

@Marc He revisado el pdf y es extremadamente específico para el servidor de ejemplo. Estoy usando un servidor completamente diferente con WebSphere ya instalado (no tengo control sobre él) y estas configuraciones no coinciden con el servidor al que intento implementar. –

Respuesta

9

Debería poder configurar un servlet filter que se ejecuta antes de los controladores REST, inspecciona el encabezado de solicitud de "Autorización", base 64 decodes, extrae el nombre de usuario y la contraseña, y los verifica. Algo como esto:

public void doFilter(ServletRequest req, 
        ServletResponse res, 
        FilterChain chain) { 
    if (request instanceof HttpServletRequest) { 
    HttpServletRequest request = (HttpServletRequest) req; 
    String authHeader = Base64.decode(request.getHeader("Authorization")); 
    String creds[] = authHeader.split(":"); 
    String username = creds[0], password = creds[1]; 
    // Verify the credentials here... 
    if (authorized) { 
     chain.doFilter(req, res, chain); 
    } else { 
     // Respond 401 Authorization Required. 
    } 
    } 
    doFilter(req, res, chain); 
} 

Todos los contenedores de servlets tienen una forma estándar de configurar las cadenas de filtros.

+0

¡Eso funcionó perfectamente! Gracias. –

4

Implementación completa basada en la respuesta de maerics.

import java.io.IOException; 

import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import org.apache.commons.lang.StringUtils; 

import sun.misc.BASE64Decoder; 

public class AuthenticationFilter implements Filter { 

    private static final String AUTHORIZATION_HEADER_NAME = "Authorization"; 
    private static final String WWW_AUTHENTICATE_HEADER_NAME = "WWW-Authenticate"; 
    private static final String WWW_AUTHENTICATE_HEADER_VALUE = "Basic realm=\"Default realm\""; 
    private static final String BASIC_AUTHENTICATION_REGEX = "Basic\\s"; 
    private static final String EMPTY_STRING = ""; 
    private static final String USERNAME_PASSWORD_SEPARATOR = ":"; 
    private static final BASE64Decoder DECODER = new BASE64Decoder(); 

    public void init(FilterConfig arg0) throws ServletException { 
    } 

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 

     HttpServletRequest httpReq = (HttpServletRequest) req; 
     HttpServletResponse httpRes = (HttpServletResponse) res; 

     String authHeader = httpReq.getHeader(AUTHORIZATION_HEADER_NAME); 

     if (authHeader == null) { 
      this.requestAuthentication(httpRes); 
      return; 
     } 

     authHeader = authHeader.replaceFirst(BASIC_AUTHENTICATION_REGEX, EMPTY_STRING); 
     authHeader = new String(DECODER.decodeBuffer(authHeader));  

     if (StringUtils.countMatches(authHeader, USERNAME_PASSWORD_SEPARATOR) != 1) { 
      this.requestAuthentication(httpRes); 
      return;   
     } 

     String[] creds = authHeader.split(USERNAME_PASSWORD_SEPARATOR); 
     String username = creds[0]; 
     String password = creds[1];   

     //TODO: implement this method 
     if (!authenticatedUser(username, password)) { 
      this.requestAuthentication(httpRes); 
      return; 
     } 

     chain.doFilter(req, res); 
    } 

    private void requestAuthentication(HttpServletResponse httpRes) { 

     httpRes.setHeader(WWW_AUTHENTICATE_HEADER_NAME, WWW_AUTHENTICATE_HEADER_VALUE); 
     httpRes.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 
    } 

    public void destroy() { 
    } 
} 
Cuestiones relacionadas