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

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开发者控制台配置

  1. 进入Google Cloud Console,创建项目并启用"Google Identity API"
  2. 创建OAuth客户端ID,应用类型选择"Web应用"
  3. 添加授权重定向URI:https://localhost:5001/signin-google(替换为你的API端口,必须和Program.cs里的CallbackPath完全一致)
  4. 复制生成的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;

四、测试流程

  1. 启动ASP.NET API(确保HTTPS端口为5001,或修改配置中的对应端口)
  2. 启动React项目:npm start(默认端口3000)
  3. 在React页面点击"使用Google登录",跳转到Google认证页面完成登录
  4. 认证成功后会自动回调到/signin-google,ASP.NET处理后重定向到React控制台页面
  5. 控制台显示当前用户信息,说明认证与用户存储流程正常

常见问题解决

  • /signin-google无法处理:检查Google开发者控制台的重定向URI是否和Program.cs的CallbackPath完全一致(包括协议、端口);确保API启用了UseAuthentication中间件
  • 跨域请求失败:确认CORS配置中的Origin是React的地址,且开启了AllowCredentials
  • 用户信息未存储:检查OnCreatingTicket事件中的代码,确保邮箱获取逻辑正确,用户创建无报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 07:35:55