[GO] Ich habe versucht, mich mit Spring Boot + Spring Security REST API anzumelden

Ich habe es möglich gemacht, mich bei dem mit Spring Boot mit Google Sign-In erstellten REST-API-Server anzumelden, damit ich aufschreiben kann, was ich getan habe.

Die Version von Spring Boot, die ich verwende, ist "1.5.7". Das meiste, was Sie unten tun, ist möglicherweise mit @ EnableOAuth2Sso möglich, aber das ist nicht interessant oder das war's.

Vorbereitung (REST-API zur Authentifizierung)

Ändern Sie vor der Unterstützung von Google Sign-In das Standardverhalten von Spring Security in ein REST-Verhalten.

Referenzseite: http://www.baeldung.com/securing-a-restful-web-service-with-spring-security

Einstiegspunkt

Wenn Sie in einer Standard-Webanwendung in einem nicht authentifizierten Zustand auf eine sichere Ressource zugreifen, werden Sie automatisch zur Authentifizierung aufgefordert. Da sich der REST-Service jedoch explizit authentifiziert, drücken Sie in einem solchen Fall einfach "401". Es wird zurückgegeben.

RestAuthenticationEntryPoint.java


@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

  @Override
  public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
  }
}

Gibt bei erfolgreicher Anmeldung "200" anstelle von "301" zurück

Wenn die Anmeldung erfolgreich ist, wird standardmäßig "301" zurückgegeben und der Bildschirm wird nach der Anmeldung zum Bildschirm geführt. In REST wird "200" jedoch einfach zurückgegeben. Erstellen Sie einen "AuthenticationSuccessHandler", der nicht umleitet, indem Sie auf den "SavedRequestAwareAuthenticationSuccessHandler" verweisen.

RestSavedRequestAwareAuthenticationSuccessHandler.java


@Component
public class RestSavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

  private RequestCache requestCache = new HttpSessionRequestCache();

  @Override
  public void onAuthenticationSuccess(HttpServletRequest request,
                                      HttpServletResponse response, Authentication authentication) {
    SavedRequest savedRequest = requestCache.getRequest(request, response);

    if (savedRequest == null) {
      clearAuthenticationAttributes(request);
      return;
    }
    String targetUrlParameter = getTargetUrlParameter();
    if (isAlwaysUseDefaultTargetUrl()
      || (targetUrlParameter != null && StringUtils.hasText(request
      .getParameter(targetUrlParameter)))) {
      requestCache.removeRequest(request, response);
      clearAuthenticationAttributes(request);
      return;
    }

    clearAuthenticationAttributes(request);
  }
}

Gibt bei fehlgeschlagener Anmeldung "401" anstelle von "302" zurück

Wenn die Anmeldung fehlschlägt, geben Sie einfach "401" zurück. Sie können den SimpleUrlAuthenticationFailureHandler von Spring so wie er ist verwenden.

Geben Sie beim Abmelden einfach "200" zurück

In ähnlicher Weise wird beim Abmelden nicht umgeleitet und nur "200" zurückgegeben. Sie können hier auch den SimpleUrlLogoutSuccessHandler von Spring verwenden.

SecurityConfig Erstellen Sie eine Konfiguration im bisherigen Status.

SecurityConfig.java


@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private RestAuthenticationEntryPoint authenticationEntryPoint;

  @Autowired
  private RestSavedRequestAwareAuthenticationSuccessHandler authenticationSuccessHandler;

  @Autowired
  private SimpleUrlAuthenticationFailureHandler authenticationFailureHandler;

  @Autowired
  private SimpleUrlLogoutSuccessHandler logoutSuccessHandler;

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .csrf().disable()
      .authorizeRequests()
        .antMatchers("/api/**").authenticated()
        .and()
      .exceptionHandling()
        .authenticationEntryPoint(authenticationEntryPoint)
        .and()
      .formLogin()
        .successHandler(authenticationSuccessHandler)
        .failureHandler(authenticationFailureHandler)
        .and()
      .logout()
        .logoutSuccessHandler(logoutSuccessHandler)
    ;
  }

  @Bean
  public SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler() {
    return new SimpleUrlAuthenticationFailureHandler();
  }

  @Bean
  public SimpleUrlLogoutSuccessHandler simpleUrlLogoutSuccessHandler() {
    return new SimpleUrlLogoutSuccessHandler();
  }
}

Implementieren Sie die Google-Anmeldung

Endlich das Hauptthema. Coco und Coco -auth) als Referenz. Von der Webanwendung (Vorderseite) wird das "id_token", das bei der Anmeldung abgerufen werden kann, in POST to "/ login" mit "x-www-form-urlencoded" implementiert. Der Parametername lautet "google_id_token".

Fix SecurityConfig

Machen Sie den formLogin () Teil der erstelltenSecurityConfig # configure (HttpSecurity http)wie folgt.

SecurityConfig.java


      .formLogin()
        .passwordParameter("google_id_token")
        .successHandler(authenticationSuccessHandler)

Ich habe gerade passwordParameter (" google_id_token ") hinzugefügt. Sie erhalten nun "id_token" als Passwort für die Authentifizierung mit Ihrem Standardbenutzernamen und -passwort.

Implementiert AuthenticationProvider

Nachdem Sie das "id_token" erhalten haben, müssen Sie nur noch die Authentifizierung implementieren.

GoogleIdAuthenticationProvider.java


@Component
public class GoogleIdAuthenticationProvider implements AuthenticationProvider {

  private final String clientId = "XXX.apps.googleusercontent.com";

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    String tokenString = (String) authentication.getCredentials();
    GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(UrlFetchTransport.getDefaultInstance(), JacksonFactory.getDefaultInstance())
      .setAudience(singletonList(clientId))
      .build();
    GoogleIdToken idToken;
    try {
      idToken = verifier.verify(tokenString);
      if (idToken == null) {
        throw new BadCredentialsException("Failed to verify token");
      }
    } catch (GeneralSecurityException|IOException e) {
      throw new AuthenticationServiceException("Failed to verify token", e);
    }

    GoogleIdToken.Payload payload = idToken.getPayload();
    String userId = payload.getSubject();
    String name = (String) payload.get("name");
    GoogleUser user = new GoogleUser(userId, name);
    List<GrantedAuthority> authorities = singletonList(new SimpleGrantedAuthority("ROLE_USER"));
    return new UsernamePasswordAuthenticationToken(user, tokenString, authorities);
  }

  @Override
  public boolean supports(Class<?> authentication) {
    return UsernamePasswordAuthenticationToken.class.equals(authentication);
  }
}

Wenn Sie sich auf eine bestimmte Domain beschränken möchten, können Sie dies tun, indem Sie "payload.getHostedDomain ()" aktivieren.

Die GoogleUser-Klasse lautet wie folgt.

GoogleUser.java


@Data
@RequiredArgsConstructor
@AllArgsConstructor
public class GoogleUser implements UserDetails {

  @NotNull
  @Setter(AccessLevel.NONE)
  private String userId;

  private String username;

  @Override
  public Collection<? extends GrantedAuthority> getAuthorities() {
    return null;
  }

  @Override
  public String getPassword() {
    return null;
  }

  @Override
  public boolean isAccountNonExpired() {
    return false;
  }

  @Override
  public boolean isAccountNonLocked() {
    return false;
  }

  @Override
  public boolean isCredentialsNonExpired() {
    return false;
  }

  @Override
  public boolean isEnabled() {
    return false;
  }
}

Sie sind jetzt bereit für die Google-Anmeldung.

Recommended Posts

Ich habe versucht, mich mit Spring Boot + Spring Security REST API anzumelden
Ich habe "License OCR" mit der Google Vision API ausprobiert
Ich habe "Receipt OCR" mit der Google Vision API ausprobiert
Ich habe versucht, die Google Cloud Vision-API zu verwenden
Ich habe Java8 + Spring Boot mit GAE SE (und seiner Entwicklungsumgebung) ausprobiert.
Ich habe APN (Remote-Benachrichtigung) mithilfe der Parse.com-REST-API ausprobiert
Ich habe versucht, unsere Dunkelheit mit der Chatwork-API aufzudecken
Ich habe versucht, die API mit dem Python-Client von echonest zu erreichen
Ich habe versucht, mit Python zu kratzen
Hallo Welt mit Google App Engine (Java 8) + Spring Boot + Gradle
Ich habe versucht, mit PyCaret zu clustern
Ich habe versucht, Raspeye und conect + mit der Web-API zu verbinden
Ich habe versucht, Follow Management mit Twitter API und Python (einfach)
Ich habe versucht, den DRF-API-Anforderungsverlauf mit django-request zu speichern
Ich habe die Google Cloud Vision-API zum ersten Mal ausprobiert
Ich habe gRPC mit Python ausprobiert
Ich habe versucht, mit Python zu kratzen
Hallo Welt mit Google App Engine (Java 11) + Spring Boot + Gradle
Ich habe versucht, die Google-API mit Ruby und Python zu erreichen. Machen Sie die Datenbank zu einer Tabelle und verwalten Sie sie mit Google Drive
Ich habe versucht, alles zu automatisieren, einschließlich der zweistufigen Authentifizierung von Google OAuth
Ich habe ChatOps mit Slack x API Gateway x Lambda (Python) x RDS ausprobiert
Ich habe versucht, die Docomo-Spracherkennungs-API und die Google Speech-API in Java zu verwenden
Betreiben Sie Nutanix mit der REST-API Teil 2
Ich habe versucht, eine Quip-API zu erstellen
Ich habe die Naro-Roman-API 2 ausprobiert
Ich habe maschinelles Lernen mit liblinear versucht
Ich habe versucht, WebScraping mit Python.
Ich habe versucht, Essen mit SinGAN zu bewegen
Ich habe versucht, DeepPose mit PyTorch zu implementieren
Ich habe Teslas API berührt
Ich habe versucht, das Gesicht mit MTCNN zu erkennen
Ich habe die neuartige API von Naruro ausprobiert
Ich habe versucht, Prolog mit Python 3.8.2 auszuführen.
Ich habe die SMTP-Kommunikation mit Python versucht
Ich habe versucht, Sätze mit GPT-2 zu generieren
Ich habe versucht, LightGBM mit Yellowbrick zu lernen
Einführung der Google Map API mit Schienen
Ich habe versucht, das Gesicht mit OpenCV zu erkennen
Ich habe versucht, die checkio-API zu verwenden
Ich habe versucht, schlechte Tweets regelmäßig mit der AWS Lambda + Twitter API zu löschen
Ich habe versucht, Zeichen aus Untertiteln zu extrahieren (OpenCV: Google Cloud Vision API)
Ich habe versucht, "Sakurai-san" LINE BOT mit API Gateway + Lambda zu erstellen
Ich habe versucht, den Authentifizierungscode der Qiita-API mit Python abzurufen.
Ich habe versucht, die Filminformationen der TMDb-API mit Python abzurufen
Ich habe versucht, die Mastodon-API mit Ruby (Faraday) / Python (Pycurl) / PHP (Curl) zu erreichen.
Ich habe versucht, den Google-Kalender mit CSV-Terminen mithilfe von Python und Google API zu aktualisieren
Ich habe eine multiple Regressionsanalyse mit Polypoly-Regression versucht
Ich habe versucht, eine SMS mit Twilio zu senden
Ich habe versucht, Amazon SQS mit Django-Sellerie zu verwenden
Streaming-Spracherkennung mit der Google Cloud Speech API
Ich habe versucht, Autoencoder mit TensorFlow zu implementieren
Ich habe Linebot mit Flasche (Anaconda) + Heroku ausprobiert
Ich habe versucht, AutoEncoder mit TensorFlow zu visualisieren
Ich habe versucht, mit Hy anzufangen
Ich habe versucht, YOUTUBE Data API V3 zu verwenden
Ich habe versucht, Selen mit Headless-Chrom zu verwenden
Ich habe versucht, Faktoren mit Titanic-Daten zu analysieren!