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

如何在ASP.NET Core with React.JS模板中实现控制器与React组件的数据交互?

ASP.NET Core + React 数据传输与JWT认证实现方案

一、.NET Core 控制器与模型基础实现

1. 定义数据模型

在项目Models目录下创建用户相关实体和请求/返回DTO:

// User.cs(数据库实体)
public class User
{
    public int Id { get; set; }
    public string Username { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string PasswordHash { get; set; } = string.Empty;
}

// LoginRequest.cs(登录请求参数)
public class LoginRequest
{
    public string Username { get; set; } = string.Empty;
    public string Password { get; set; } = string.Empty;
}

// RegisterRequest.cs(注册请求参数)
public class RegisterRequest
{
    public string Username { get; set; } = string.Empty;
    public string Email { get; set; } = string.Empty;
    public string Password { get; set; } = string.Empty;
}

// AuthResponse.cs(登录返回结果)
public class AuthResponse
{
    public string Token { get; set; } = string.Empty;
    public string Username { get; set; } = string.Empty;
}

2. 编写认证控制器

创建AuthController.cs,处理登录、注册逻辑:

[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
    private readonly DataContext _context;
    private readonly IConfiguration _config;

    public AuthController(DataContext context, IConfiguration config)
    {
        _context = context;
        _config = config;
    }

    // 注册接口
    [HttpPost("register")]
    public async Task<ActionResult<User>> Register(RegisterRequest request)
    {
        using var hmac = new HMACSHA512();
        var user = new User
        {
            Username = request.Username,
            Email = request.Email,
            PasswordHash = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(request.Password)))
        };

        _context.Users.Add(user);
        await _context.SaveChangesAsync();
        return Ok(user);
    }

    // 登录接口
    [HttpPost("login")]
    public async Task<ActionResult<AuthResponse>> Login(LoginRequest request)
    {
        var user = await _context.Users.FirstOrDefaultAsync(u => u.Username == request.Username);
        if (user == null) return Unauthorized("用户名错误");

        using var hmac = new HMACSHA512();
        var computedHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(request.Password));
        if (!computedHash.SequenceEqual(Convert.FromBase64String(user.PasswordHash)))
            return Unauthorized("密码错误");

        var token = CreateToken(user);
        return Ok(new AuthResponse { Token = token, Username = user.Username });
    }

    // 生成JWT私有方法
    private string CreateToken(User user)
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, user.Username),
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())
        };

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config.GetSection("AppSettings:Token").Value!));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);

        var token = new JwtSecurityToken(
            claims: claims,
            expires: DateTime.Now.AddDays(1),
            signingCredentials: creds);

        return new JwtSecurityTokenHandler().WriteToken(token);
    }
}

二、配置JWT认证服务

在Program.cs中添加认证授权相关配置:

var builder = WebApplication.CreateBuilder(args);

// 注册数据库上下文
builder.Services.AddDbContext<DataContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

// 配置JWT认证
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration.GetSection("AppSettings:Token").Value!)),
            ValidateIssuer = false,
            ValidateAudience = false
        };
    });

builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();

var app = builder.Build();

// 中间件顺序不可乱
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

// 先认证再授权
app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller}/{action=Index}/{id?}");

app.MapFallbackToFile("index.html");

app.Run();

在appsettings.json中添加密钥和数据库连接配置:

{
  "AppSettings": {
    "Token": "你的32位以上安全密钥"
  },
  "ConnectionStrings": {
    "DefaultConnection": "你的SQL Server连接字符串"
  }
}

三、React端数据交互实现

1. 登录组件(axios请求)

在ClientApp/src/components下创建Login.jsx:

import { useState } from 'react';
import axios from 'axios';

export default function Login() {
    const [username, setUsername] = useState('');
    const [password, setPassword] = useState('');

    const handleLogin = async (e) => {
        e.preventDefault();
        try {
            const res = await axios.post('/api/auth/login', { username, password });
            localStorage.setItem('token', res.data.token);
            localStorage.setItem('username', res.data.username);
            window.location.href = '/';
        } catch (err) {
            alert(err.response.data);
        }
    };

    return (
        <form onSubmit={handleLogin}>
            <div>
                <label>用户名</label>
                <input
                    type="text"
                    value={username}
                    onChange={(e) => setUsername(e.target.value)}
                    required
                />
            </div>
            <div>
                <label>密码</label>
                <input
                    type="password"
                    value={password}
                    onChange={(e) => setPassword(e.target.value)}
                    required
                />
            </div>
            <button type="submit">登录</button>
        </form>
    );
}

2. 注册组件示例

import { useState } from 'react';
import axios from 'axios';

export default function Register() {
    const [username, setUsername] = useState('');
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');

    const handleRegister = async (e) => {
        e.preventDefault();
        try {
            await axios.post('/api/auth/register', { username, email, password });
            alert('注册成功,请登录');
            window.location.href = '/login';
        } catch (err) {
            alert(err.response.data);
        }
    };

    return (
        <form onSubmit={handleRegister}>
            <div>
                <label>用户名</label>
                <input
                    type="text"
                    value={username}
                    onChange={(e) => setUsername(e.target.value)}
                    required
                />
            </div>
            <div>
                <label>邮箱</label>
                <input
                    type="email"
                    value={email}
                    onChange={(e) => setEmail(e.target.value)}
                    required
                />
            </div>
            <div>
                <label>密码</label>
                <input
                    type="password"
                    value={password}
                    onChange={(e) => setPassword(e.target.value)}
                    required
                />
            </div>
            <button type="submit">注册</button>
        </form>
    );
}

3. 受保护路由与授权请求

在App.jsx中配置路由保护:

import { Routes, Route, Navigate } from 'react-router-dom';
import Login from './components/Login';
import Register from './components/Register';
import Dashboard from './components/Dashboard';

const ProtectedRoute = ({ children }) => {
    const token = localStorage.getItem('token');
    return token ? children : <Navigate to="/login" />;
};

function App() {
    return (
        <Routes>
            <Route path="/login" element={<Login />} />
            <Route path="/register" element={<Register />} />
            <Route path="/" element={
                <ProtectedRoute>
                    <Dashboard />
                </ProtectedRoute>
            } />
        </Routes>
    );
}

export default App;

在Dashboard.jsx中请求授权接口:

import { useState, useEffect } from 'react';
import axios from 'axios';

export default function Dashboard() {
    const [forecasts, setForecasts] = useState([]);

    useEffect(() => {
        const fetchData = async () => {
            try {
                const token = localStorage.getItem('token');
                const res = await axios.get('/weatherforecast', {
                    headers: { Authorization: `Bearer ${token}` }
                });
                setForecasts(res.data);
            } catch (err) {
                alert('请重新登录');
                window.location.href = '/login';
            }
        };
        fetchData();
    }, []);

    return (
        <div>
            <h1>欢迎 {localStorage.getItem('username')}</h1>
            <ul>
                {forecasts.map(f => (
                    <li key={f.date}>
                        {f.date}: {f.summary} - {f.temperatureC}°C
                    </li>
                ))}
            </ul>
        </div>
    );
}

最后给WeatherForecast控制器添加授权特性:

[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    // 原有代码...
}

内容的提问来源于stack exchange,提问作者Việt Tùng Nguyễn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 17:33:15