autenticazione X.509 per microservizi con JavaEE [chiuso]

0

Sto provando a progettare un'app basata sull'architettura dei microservizi. Il backend è scritto in JavaEE (micro profilo, non Spring Boot), mentre per front end vorrei usare Angular5.

Ora mi chiedo come implementare un'autenticazione che richiederebbe all'utente di presentare un certificato X.509 valido (file .p12) firmato con la mia CA autofirmata. Dopo che l'utente ha presentato il suo certificato, gli avrei chiesto la sua password (memorizzata nel database), mentre leggevo la sua e-mail dal certificato e lo registrava in base a quei due input. Se l'utente è autenticato correttamente, gli invierò il token JWT, con il quale accederà ai dati delle mie pagine angolari.

Non so come iniziare con un'implementazione di questo tipo, è una cosa fatta dal lato client, o è gestita da un lato server e, in caso affermativo, da quando il mio back-end è solo API REST.

Sto cercando un'idea generale su come implementare questo e, se possibile, una letteratura che sta affrontando questo tipo di requisito.

Ho vari micro servizi che eseguono la logica della mia applicazione e vorrei supportare diversi tipi di utenti: utenti regolari, moderatori e amministratori. Ogni microservizio può avere diverse regole di accesso. (ad esempio, l'opzione per recuperare tutti i dati è disponibile per tutti, l'opzione per recuperare un particolare dato è riservata agli utenti registrati, mentre l'opzione per creare nuovi dati è disponibile solo per mod e amministratori). Voglio che gli utenti normali effettuino il login solo usando la loro email e password (entrambi memorizzati nel DB), non ho problemi con questo, tuttavia vorrei che mod e amministratori debbano presentare il certificato x509 per poter accedere. In entrambi i casi, avrei quindi generato un token JWT e inviato all'utente (in token scriverei il loro ruolo, che determinerebbe se è possibile eseguire un'azione o meno).

Non sono interessato all'implementazione come lo sono io nel flusso di lavoro generale che la mia app dovrebbe supportare per implementare questa cosa. Posso capire ogni dettaglio in seguito, tuttavia non sono sicuro di come procedere in REST / Angular way. Ho idea di come farlo con l'app di rendering del server, ma ora voglio migrare al rendering client.

    
posta Miha Jamsek 30.01.2018 - 22:33
fonte

1 risposta

1

Questo probabilmente appartiene allo stackoverflow, ma ecco un'implementazione abbastanza minima del recupero del client-cert usando i filtri JAX-RS:

import java.io.IOException;
import java.security.Principal;
import java.security.cert.X509Certificate;

import javax.annotation.Priority;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.ext.Provider;

@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements javax.ws.rs.container.ContainerRequestFilter
{
  @Context
  private ResourceInfo resourceInfo;

  private static final ResponseBuilder ACCESS_DENIED = Response.status(Response.Status.UNAUTHORIZED).entity("User not authenticated");
  private static final ResponseBuilder ACCESS_FORBIDDEN = Response.status(Response.Status.FORBIDDEN).entity("Access denied");

  @Override
  public void filter(ContainerRequestContext request) throws IOException
  {
    Principal principal = getPrincipal(request);

    if (principal == null) {
      abortAccessDenied(request);
      return;
    }

    User user = new User(principal);

    request.setSecurityContext(new ReportsSecurityContext(user));

    if (!user.isAllowed(request)) {
      abortNotAllowed(request);
    }
  }

  private void abortNotAllowed(ContainerRequestContext request)
  {
    request.abortWith(ACCESS_FORBIDDEN.build());
  }

  private void abortAccessDenied(ContainerRequestContext request)
  {
    request.abortWith(ACCESS_DENIED.build());
  }

  private static Principal getPrincipal(ContainerRequestContext requestContext) throws IOException
  {
    X509Certificate[] certificates = (X509Certificate[]) requestContext.getProperty("javax.servlet.request.X509Certificate");

    if (certificates != null && certificates.length > 0) {
      return certificates[0].getSubjectX500Principal();
    } else {
      return null;
    }
  }
}

User è un tipo personalizzato e dovrai registrare il filtro. Dovrai anche assicurarti che il tuo certificato CA autofirmato si trovi nel tuo truststore.

Dovrai anche configurare il tuo SSL per utilizzare le autorizzazioni client. Uso Jetty incorporato e setWantClientAuth(true) o setNeedClientAuth(true) su SslContextFactory .

    
risposta data 30.01.2018 - 23:40
fonte

Leggi altre domande sui tag