Überprüfen Sie das von Firebase auf der Serverseite erhaltene ID-Token (Java + SpringBoot).

Einführung

Sie können ein ID-Token (JWT) erhalten, wenn Sie sich mit der Firebase-Authentifizierung anmelden. Wenn Sie beispielsweise eine Anmeldeauthentifizierung mit SPA durchführen, möchten Sie sich möglicherweise mit Firebase mit einem Client (JavaScript) anmelden, das erworbene Token an den Server senden und die UID in JWT dem von der Anwendung verwalteten Benutzer zuordnen. Ich denke, dort ist.

スクリーンショット 2019-02-19 14.53.20.png

Dieses Mal werde ich hauptsächlich die Überprüfungsmethode von JWT auf der Serverseite schreiben (Java + SpringBoot).

Client-Implementierung

Dieses Mal werde ich Nuxt verwenden. So erhalten und senden Sie Token.

Authentifizierungsprozess (Auszug)


async signin() {
  try {
    //Authentifizieren Sie sich mit E-Mail-Adresse und Passwort
    await firebase.auth().signInWithEmailAndPassword(this.email, this.password)

    //ID-Token abrufen (JWT)
    const token = await firebase.auth().currentUser.getIdToken(true)

    //Im lokalen Speicher speichern
    localStorage.setItem('token', token)

    //Übergang zur Seite nach der Authentifizierung
    this.$router.push('/')
  } catch (e) {
    //Zum Zeitpunkt des Authentifizierungsfehlers oder Token-Erfassungsfehlers
    console.log(e)
  }
}

~/plugins/axios.js


export default function ({ $axios }) {
  $axios.onRequest(config => {
    const token = localStorage.getItem('token');
    if (token) {
      //Wenn sich im lokalen Speicher ein Token befindet, geben Sie es an den Anforderungsheader weiter (Autorisierung).
      config.headers.common['Authorization'] = "Bearer " + token;
    }
  })
}

Serverseitige Implementierung

Verwenden Sie den OnecePerRequestFilter von Spring Security.

Darüber hinaus werden die folgenden Bibliotheken verwendet.

Bibliotheksname Verwenden
OkHttp HTTP-Client
jjwt JWT-Überprüfung

LoginFilter.java


@Component
public class LoginFilter extends OncePerRequestFilter {

  //Registrieren Sie ObjectMapper im Voraus als Bean.
  @Autowired
  ObjectMapper objectMapper;

  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
      FilterChain filterChain) throws ServletException, IOException {

    //Legen Sie die Anmeldebenutzerinformationen im Kontext fest
    SecurityContextHolder.getContext().setAuthentication(new PreAuthenticatedAuthenticationToken(
        auth(request), null));

    filterChain.doFilter(request, response);
  }

  //Holen Sie sich Login-Benutzerinformationen
  private LoginUser auth(HttpServletRequest request) {
    
    //JWT aus dem Anforderungsheader extrahieren
    String token = getToken(request);

    try {

      //Überprüfen Sie JWT, erhalten Sie Ansprüche
      //Wenn die Validierung fehlschlägt, wird eine Ausnahme ausgelöst.
      Jws<Claims> claim = Jwts.parser()
          .setSigningKeyResolver(new GoogleSigningKeyResolver()) //Benötigen Sie Ihren eigenen Resolver
          .parseClaimsJws(token);

      //Holen Sie sich Uid aus dem Körperteil des Anspruchs
      String uid = (String)claim.getBody().get("user_id");

      //Holen Sie sich UID und suchen Sie nach Benutzerinformationen
      User user = userService.findByUid(uid);

      if(user == null){
        throw new BadCredentialsException("Benutzer existiert nicht");
      }

      return new LoginUser(user);

    } catch (Exception e) {
      throw new BadCredentialsException("Ungültiger Token");
    }
  }

  //Holen Sie sich das Token aus dem Anforderungsheader.
  private String getToken(HttpServletRequest request) {
    String token = request.getHeader("Authorization");
    if (token == null || !token.startsWith("Bearer ")) {
      return null;
    }
    return token.substring("Bearer ".length());
  }

  /**
   *Wir geben den öffentlichen Schlüssel zurück, der zum Signieren verwendet wurde.
   * 
   * @author h.ono
   *
   */
  public class GoogleSigningKeyResolver extends SigningKeyResolverAdapter {

    @Override
    public Key resolveSigningKey(JwsHeader jwsHeader, Claims claims) {

      try {
        Map<String, Object> map = getJwks();

        if (map.isEmpty()) {
          return null;
        }

        String keyValue = (String) map.get(jwsHeader.getKeyId());

        if (keyValue == null) {
          return null;
        }
        //Wichtiger Punkt
        //Entfernen Sie die Start- (BEGIN) und Endetiketten (END).
        keyValue = keyValue
            .replaceAll("-----BEGIN CERTIFICATE-----\n", "")
            .replaceAll("-----END CERTIFICATE-----\n", "");

        InputStream in = new ByteArrayInputStream(Base64.decodeBase64(keyValue.getBytes("UTF-8")));
        X509Certificate certificate = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(in);
        return certificate.getPublicKey();

      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }

    /**
     *Holen Sie sich JWKS von Google.
     * 
     * @return JWKS
     */
    private Map<String, Object> getJwks() {
      OkHttpClient client = new OkHttpClient();
      Request request = new Request.Builder()
          .url("https://www.googleapis.com/robot/v1/metadata/x509/[email protected]")
          .build();
      try (Response response = client.newCall(request).execute()) {
        return objectMapper.readValue(response.body().string(), new TypeReference<Map<String, Object>>() {
        });
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
  }

}

abschließend

Ich konnte die von Firebase erhaltene UID dem Benutzer zuordnen, der die App hat. Ich habe viel recherchiert, aber der größte Teil der Authentifizierung wurde auf der Clientseite abgeschlossen, sodass ich Schwierigkeiten hatte, zu einer Methode wie dieser zu gelangen. .. ..

Bei der Überprüfung von JWT habe ich auch versucht, java-jwt von auth0 bereitzustellen, aber beim Abrufen des öffentlichen Schlüssels Ich konnte es wahrscheinlich nicht bekommen, weil es das X.509-Format nicht unterstützt.

Referenzseite

Recommended Posts

Überprüfen Sie das von Firebase auf der Serverseite erhaltene ID-Token (Java + SpringBoot).
Kick ShellScript auf dem Server von Java
[Java] So rufen Sie die von HTML auf der Serverseite übergebenen Parameter ab
Migrieren Sie von Java zu Server Side Kotlin + Spring-Boot
Verwenden der Datenbank (SQL Server 2014) aus einem Java-Programm 2018/01/04
JSON in Java und Jackson Teil 1 Gibt JSON vom Server zurück
Apache Geode-Einfache Möglichkeit, Logik auf der Serverseite auszuführen
So deaktivieren Sie Set-Cookie über die API auf der Vorderseite
Installieren Sie das memcached Plugin unter MySQL und greifen Sie von Java aus zu