You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 5+Spring Boot集成Google OAuth第三方登录实现求助

Hey there! Let's walk through how to get OAuth2 login with Google/Facebook working for your wishlist app, and lock down access so users only see their own data. Since you already have a working CRUD setup with Spring Boot + Angular 5, we'll build right on top of that.


Backend Setup (Spring Boot)

First, let's tackle the Spring side to handle OAuth authentication and resource filtering.

1. Add Dependencies

Update your pom.xml to include OAuth2 client and Spring Security support:

<dependencies>
    <!-- Spring Security OAuth2 Client -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
    <!-- Spring Security -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <!-- Your existing dependencies (Spring Data JPA, Web, etc.) -->
</dependencies>

2. Configure OAuth Providers

Add your Google/Facebook client credentials to application.yml:

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: YOUR_GOOGLE_CLIENT_ID
            client-secret: YOUR_GOOGLE_CLIENT_SECRET
            scope: openid,profile,email
          facebook:
            client-id: YOUR_FACEBOOK_CLIENT_ID
            client-secret: YOUR_FACEBOOK_CLIENT_SECRET
            scope: public_profile,email
        provider:
          facebook:
            authorization-uri: https://www.facebook.com/v18.0/dialog/oauth
            token-uri: https://graph.facebook.com/v18.0/oauth/access_token
            user-info-uri: https://graph.facebook.com/v18.0/me?fields=id,name,email
            user-name-attribute: id

(You'll get these credentials from Google Cloud Console and Facebook Developers Portal)

3. Secure Your API & OAuth Login

Create a security config class to enforce authentication and enable OAuth2 login:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            // Allow CORS for your Angular frontend
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
            // Disable CSRF for API requests (adjust if needed)
            .csrf(csrf -> csrf.disable())
            // Require auth for all endpoints
            .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
            // Enable OAuth2 login flow
            .oauth2Login(Customizer.withDefaults())
            // Enable JWT resource server validation
            .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
        
        return http.build();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(List.of("http://localhost:4200")); // Your Angular URL
        config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
        config.setAllowedHeaders(List.of("*"));
        config.setAllowCredentials(true);
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return source;
    }
}

You need to map the OAuth2 user data to your existing User entity. Add fields like provider (google/facebook) and providerId (the unique ID from the OAuth provider) to your User model, then create a repository method to find users by these fields:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByProviderAndProviderId(String provider, String providerId);
}

Then, use an OAuth2UserService to auto-create a user when they first log in:

@Service
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {

    private final UserRepository userRepo;

    public CustomOAuth2UserService(UserRepository userRepo) {
        this.userRepo = userRepo;
    }

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2UserService<OAuth2UserRequest, OAuth2User> delegate = new DefaultOAuth2UserService();
        OAuth2User oAuth2User = delegate.loadUser(userRequest);

        String provider = userRequest.getClientRegistration().getRegistrationId();
        String providerId = oAuth2User.getAttribute(provider.equals("google") ? "sub" : "id");
        String email = oAuth2User.getAttribute("email");
        String name = oAuth2User.getAttribute("name");

        // Create user if they don't exist
        User user = userRepo.findByProviderAndProviderId(provider, providerId)
                .orElseGet(() -> {
                    User newUser = new User();
                    newUser.setProvider(provider);
                    newUser.setProviderId(providerId);
                    newUser.setEmail(email);
                    newUser.setName(name);
                    return userRepo.save(newUser);
                });

        // Return a custom OAuth2User with your local user ID
        return new DefaultOAuth2User(
                Collections.singleton(new SimpleGrantedAuthority("ROLE_USER")),
                oAuth2User.getAttributes(),
                provider.equals("google") ? "sub" : "id"
        );
    }
}

5. Filter Resources to the Current User

In your wishlist service, fetch only the items belonging to the logged-in user:

@Service
public class WishlistService {

    private final WishlistRepository wishlistRepo;
    private final UserRepository userRepo;

    public WishlistService(WishlistRepository wishlistRepo, UserRepository userRepo) {
        this.wishlistRepo = wishlistRepo;
        this.userRepo = userRepo;
    }

    public List<WishlistItem> getCurrentUserWishlist() {
        // Get the authenticated OAuth2 user
        OAuth2AuthenticationToken auth = (OAuth2AuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        String provider = auth.getAuthorizedClientRegistrationId();
        String providerId = auth.getPrincipal().getAttribute(provider.equals("google") ? "sub" : "id");

        // Find the local user
        User user = userRepo.findByProviderAndProviderId(provider, providerId)
                .orElseThrow(() -> new RuntimeException("User not found"));

        // Return only their wishlist items
        return wishlistRepo.findByUser(user);
    }
}

Frontend Setup (Angular 5)

Now let's set up the Angular side to handle OAuth login and attach tokens to API requests.

1. Install OAuth Library

Use angular-oauth2-oidc (supports Angular 5) to handle the OAuth flow:

npm install angular-oauth2-oidc@4.0.0 --save

2. Configure OAuth Service

Add the OAuth module to app.module.ts and configure the service:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { OAuthModule, OAuthService, JwksValidationHandler } from 'angular-oauth2-oidc';

import { AppComponent } from './app.component';
import { AuthInterceptor } from './auth.interceptor';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    HttpClientModule,
    OAuthModule.forRoot()
  ],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
  constructor(private oauthService: OAuthService) {
    this.configureOAuth();
  }

  configureOAuth() {
    // Google configuration
    this.oauthService.configure({
      clientId: 'YOUR_GOOGLE_CLIENT_ID',
      issuer: 'https://accounts.google.com',
      redirectUri: window.location.origin + '/callback',
      scope: 'openid profile email',
      responseType: 'id_token token',
      showDebugInformation: true
    });

    this.oauthService.tokenValidationHandler = new JwksValidationHandler();
    this.oauthService.loadDiscoveryDocumentAndTryLogin();
  }
}

3. Add Login Buttons & Callback Component

Create a simple login component with Google/Facebook options:

<!-- login.component.html -->
<button (click)="loginWithGoogle()">Login with Google</button>
<button (click)="loginWithFacebook()">Login with Facebook</button>
// login.component.ts
import { Component } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html'
})
export class LoginComponent {
  constructor(private oauthService: OAuthService) {}

  loginWithGoogle() {
    this.oauthService.initLoginFlow();
  }

  loginWithFacebook() {
    // Reconfigure for Facebook and start flow
    this.oauthService.configure({
      clientId: 'YOUR_FACEBOOK_CLIENT_ID',
      issuer: 'https://graph.facebook.com',
      redirectUri: window.location.origin + '/callback',
      scope: 'public_profile email',
      responseType: 'token',
      showDebugInformation: true
    });
    this.oauthService.initLoginFlow();
  }
}

Create a callback component to handle the OAuth redirect (just a blank component that redirects after login):

// callback.component.ts
import { Component, OnInit } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { Router } from '@angular/router';

@Component({
  selector: 'app-callback',
  template: '<p>Logging in...</p>'
})
export class CallbackComponent implements OnInit {
  constructor(private oauthService: OAuthService, private router: Router) {}

  ngOnInit() {
    this.oauthService.loadDiscoveryDocumentAndLogin().then(() => {
      this.router.navigate(['/wishlist']);
    });
  }
}

4. Auto-Attach Auth Tokens to API Requests

Create an interceptor to add the Bearer token to every API call:

// auth.interceptor.ts
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';
import { OAuthService } from 'angular-oauth2-oidc';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private oauthService: OAuthService) {}

  intercept(req: HttpRequest<any>, next: HttpHandler) {
    const authToken = this.oauthService.getAccessToken();
    if (authToken) {
      const authReq = req.clone({
        headers: req.headers.set('Authorization', `Bearer ${authToken}`)
      });
      return next.handle(authReq);
    }
    return next.handle(req);
  }
}

Quick Troubleshooting Tips
  • Callback Mismatch: Make sure the redirect URI in your Google/Facebook developer console matches exactly what's in your config (e.g., http://localhost:4200/callback).
  • CORS Errors: Double-check your Spring CORS config allows your Angular origin.
  • Token Validation: Ensure your backend correctly validates JWT tokens from Google/Facebook (Spring's OAuth2 resource server handles this automatically if configured properly).
  • User Creation: Verify that new users are being saved to your database on first login.

内容的提问来源于stack exchange,提问作者Sesha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:13:21