ASP.NET API集成Google OAuth+React前端:认证及用户存储问题求助
分步解决方案:ASP.NET API + Google OAuth + React + 用户存储
一、ASP.NET API 端配置
1. 创建项目与安装依赖
- 创建ASP.NET Core Web API项目(.NET 7+),取消勾选"Use Authentication"
- 安装NuGet包:
Install-Package Microsoft.AspNetCore.Authentication.Google Install-Package Microsoft.EntityFrameworkCore.SqlServer Install-Package Microsoft.AspNetCore.Identity.EntityFrameworkCore
2. 配置AppSettings.json
添加以下配置(替换为你的Google凭证和数据库连接字符串):
{ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=GoogleAuthDemo;Trusted_Connection=True;MultipleActiveResultSets=true" }, "Authentication": { "Google": { "ClientId": "你的Google Client ID", "ClientSecret": "你的Google Client Secret" } }, "AllowedHosts": "*" }
3. 创建数据库上下文(存储用户)
新建Data/AppDbContext.cs:
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace GoogleAuthDemo.Data; public class AppDbContext : IdentityDbContext { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } }
4. 配置Program.cs
修改Program.cs,添加认证、Identity和数据库配置:
using GoogleAuthDemo.Data; using Microsoft.AspNetCore.Authentication.Google; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); // 添加DbContext builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); // 添加Identity服务 builder.Services.AddIdentityCore<IdentityUser>() .AddEntityFrameworkStores<AppDbContext>() .AddSignInManager() .AddDefaultTokenProviders(); // 添加Google认证 builder.Services.AddAuthentication(options => { options.DefaultScheme = IdentityConstants.ApplicationScheme; options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme; }) .AddCookie(IdentityConstants.ApplicationScheme, options => { // 配置Cookie跨域(适配React前端) options.Cookie.SameSite = SameSiteMode.None; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; options.Cookie.HttpOnly = true; // 登录成功后的回调路径(可自定义,这里跳转到React首页) options.LoginPath = "/api/auth/google-login"; options.ReturnUrlParameter = "returnUrl"; }) .AddGoogle(options => { options.ClientId = builder.Configuration["Authentication:Google:ClientId"]!; options.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"]!; // 回调路径必须和Google开发者控制台配置一致 options.CallbackPath = "/signin-google"; // 获取用户的邮箱、姓名等信息 options.Scope.Add("email"); options.Scope.Add("profile"); // 保存Token到Cookie options.SaveTokens = true; // 处理Google返回的用户信息,同步到数据库 options.Events.OnCreatingTicket = async context => { var signInManager = context.HttpContext.RequestServices.GetRequiredService<SignInManager<IdentityUser>>(); var userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<IdentityUser>>(); // 从Google获取用户邮箱 var email = context.User.FindFirst(System.Security.Claims.ClaimTypes.Email)?.Value; if (string.IsNullOrEmpty(email)) { throw new Exception("无法获取Google用户邮箱"); } // 检查数据库中是否已有该用户 var user = await userManager.FindByEmailAsync(email); if (user == null) { // 创建新用户 user = new IdentityUser { UserName = email, Email = email, EmailConfirmed = true }; var createResult = await userManager.CreateAsync(user); if (!createResult.Succeeded) { throw new Exception($"创建用户失败:{string.Join(", ", createResult.Errors.Select(e => e.Description))}"); } } // 登录用户(生成身份Cookie) await signInManager.SignInAsync(user, isPersistent: false); }; }); // 添加CORS,允许React前端跨域请求 builder.Services.AddCors(options => { options.AddPolicy("ReactPolicy", policy => { policy.WithOrigins("http://localhost:3000") // React默认端口 .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); // 允许携带Cookie }); }); builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // 迁移数据库(首次运行时创建表) using (var scope = app.Services.CreateScope()) { var services = scope.ServiceProvider; var dbContext = services.GetRequiredService<AppDbContext>(); await dbContext.Database.MigrateAsync(); } if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); // 启用CORS app.UseCors("ReactPolicy"); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
5. 创建认证控制器
新建Controllers/AuthController.cs:
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace GoogleAuthDemo.Controllers; [ApiController] [Route("api/[controller]")] public class AuthController : ControllerBase { // 跳转至Google认证页面 [HttpGet("google-login")] public IActionResult GoogleLogin(string returnUrl = "/") { var redirectUrl = Url.Action("GoogleCallback", "Auth", new { returnUrl }); var properties = new AuthenticationProperties { RedirectUri = redirectUrl }; return Challenge(properties, GoogleDefaults.AuthenticationScheme); } // Google认证回调处理(可选,这里直接跳转到React前端) [HttpGet("google-callback")] public IActionResult GoogleCallback(string returnUrl = "/") { // 认证成功后重定向到React首页 return Redirect($"http://localhost:3000{returnUrl}"); } // 获取当前登录用户信息 [HttpGet("me")] [Authorize] public IActionResult GetCurrentUser() { var user = new { Id = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value, Email = User.FindFirst(System.Security.Claims.ClaimTypes.Email)?.Value, Name = User.FindFirst(System.Security.Claims.ClaimTypes.Name)?.Value }; return Ok(user); } // 退出登录 [HttpPost("logout")] [Authorize] public async Task<IActionResult> Logout() { await HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme); return Ok("退出成功"); } }
二、Google开发者控制台配置
- 进入Google Cloud Console,创建项目并启用"Google Identity API"
- 创建OAuth客户端ID,应用类型选择"Web应用"
- 添加授权重定向URI:
https://localhost:5001/signin-google(替换为你的API端口,必须和Program.cs里的CallbackPath完全一致) - 复制生成的ClientId和ClientSecret到AppSettings.json
三、React前端配置
1. 创建React项目
npx create-react-app google-auth-react cd google-auth-react npm install axios react-router-dom
2. 编写登录组件
修改src/App.js:
import { useState, useEffect } from 'react'; import axios from 'axios'; import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom'; function Login() { const handleLogin = () => { // 跳转到API的Google登录接口 window.location.href = 'https://localhost:5001/api/auth/google-login'; }; return ( <div style={{ padding: '2rem' }}> <h2>登录</h2> <button onClick={handleLogin} style={{ padding: '0.5rem 1rem', fontSize: '1rem' }}>使用Google登录</button> </div> ); } function Dashboard() { const [user, setUser] = useState(null); useEffect(() => { // 获取当前用户信息 axios.get('https://localhost:5001/api/auth/me', { withCredentials: true }) .then(res => setUser(res.data)) .catch(err => console.error('获取用户信息失败:', err)); }, []); const handleLogout = () => { axios.post('https://localhost:5001/api/auth/logout', {}, { withCredentials: true }) .then(() => { setUser(null); window.location.href = '/'; }) .catch(err => console.error('退出失败:', err)); }; if (!user) { return <div style={{ padding: '2rem' }}>加载中...</div>; } return ( <div style={{ padding: '2rem' }}> <h2>控制台</h2> <p>用户ID: {user.Id}</p> <p>邮箱: {user.Email}</p> <p>姓名: {user.Name}</p> <button onClick={handleLogout} style={{ padding: '0.5rem 1rem', fontSize: '1rem' }}>退出登录</button> </div> ); } function App() { return ( <Router> <nav style={{ padding: '1rem', background: '#f0f0f0' }}> <Link to="/" style={{ marginRight: '1rem' }}>首页</Link> <Link to="/dashboard">控制台</Link> </nav> <Routes> <Route path="/" element={<Login />} /> <Route path="/dashboard" element={<Dashboard />} /> </Routes> </Router> ); } export default App;
四、测试流程
- 启动ASP.NET API(确保HTTPS端口为5001,或修改配置中的对应端口)
- 启动React项目:
npm start(默认端口3000) - 在React页面点击"使用Google登录",跳转到Google认证页面完成登录
- 认证成功后会自动回调到
/signin-google,ASP.NET处理后重定向到React控制台页面 - 控制台显示当前用户信息,说明认证与用户存储流程正常
常见问题解决
- /signin-google无法处理:检查Google开发者控制台的重定向URI是否和Program.cs的CallbackPath完全一致(包括协议、端口);确保API启用了
UseAuthentication中间件 - 跨域请求失败:确认CORS配置中的Origin是React的地址,且开启了
AllowCredentials - 用户信息未存储:检查
OnCreatingTicket事件中的代码,确保邮箱获取逻辑正确,用户创建无报错
内容的提问来源于stack exchange,提问作者PH31
相关产品推荐
相关产品推荐

