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.
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; } }
4. Link OAuth Users to Your Local User Entity
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); } }
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); } }
- 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

