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

能否用.NET Core Identity为Next.js+REST API实现登录鉴权?

可以用.NET Core Identity实现你的REST API认证授权方案

完全可以按照你的设想实现这个流程,.NET Core Identity本身支持集成JWT生成,配合Razor Pages的登录流程,能无缝衔接Next.js前端。以下是具体实现步骤和注意事项:

实现步骤

1. 配置.NET项目的Identity与JWT服务

在Program.cs中完成Identity和JWT认证的基础配置:

var builder = WebApplication.CreateBuilder(args);

// 配置Identity与数据库上下文
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

// 配置JWT认证服务
builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidIssuer = builder.Configuration["Jwt:Issuer"],
        ValidAudience = builder.Configuration["Jwt:Audience"],
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
    };
});

// 添加必要服务
builder.Services.AddAuthorization();
builder.Services.AddRazorPages();
builder.Services.AddControllers(); // 启用API控制器支持

var app = builder.Build();

// 中间件配置
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

// 映射路由
app.MapRazorPages();
app.MapControllers();

app.Run();

2. 在Razor Pages登录页生成JWT并跳转回Next.js

在Login.cshtml.cs的登录逻辑中,验证用户成功后生成JWT,通过HttpOnly Cookie传递(比URL参数更安全),再跳转至Next.js页面:

public class LoginModel : PageModel
{
    private readonly SignInManager<IdentityUser> _signInManager;
    private readonly UserManager<IdentityUser> _userManager;
    private readonly IConfiguration _configuration;

    public LoginModel(SignInManager<IdentityUser> signInManager, UserManager<IdentityUser> userManager, IConfiguration configuration)
    {
        _signInManager = signInManager;
        _userManager = userManager;
        _configuration = configuration;
    }

    [BindProperty]
    public InputModel Input { get; set; }

    public string ReturnUrl { get; set; }

    public class InputModel
    {
        [Required]
        [EmailAddress]
        public string Email { get; set; }

        [Required]
        [DataType(DataType.Password)]
        public string Password { get; set; }

        [Display(Name = "Remember me?")]
        public bool RememberMe { get; set; }
    }

    public async Task<IActionResult> OnPostAsync(string returnUrl = null)
    {
        returnUrl ??= Url.Content("~/");

        if (ModelState.IsValid)
        {
            var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
            if (result.Succeeded)
            {
                // 获取当前用户并构建Claims
                var user = await _userManager.FindByEmailAsync(Input.Email);
                var claims = new List<Claim>
                {
                    new Claim(ClaimTypes.NameIdentifier, user.Id),
                    new Claim(ClaimTypes.Email, user.Email)
                    // 可添加其他业务所需的Claims
                };

                // 生成JWT
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
                var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                var token = new JwtSecurityToken(
                    issuer: _configuration["Jwt:Issuer"],
                    audience: _configuration["Jwt:Audience"],
                    claims: claims,
                    expires: DateTime.Now.AddHours(1),
                    signingCredentials: creds);

                var tokenString = new JwtSecurityTokenHandler().WriteToken(token);

                // 将token存入HttpOnly Cookie
                Response.Cookies.Append("AuthToken", tokenString, new CookieOptions
                {
                    HttpOnly = true,
                    Secure = true,
                    SameSite = SameSiteMode.None, // 跨域场景下需配置,根据实际环境调整
                    Expires = DateTime.Now.AddHours(1)
                });

                // 跳转回Next.js目标页面
                return Redirect("https://your-nextjs-domain.com/dashboard");
            }
            ModelState.AddModelError(string.Empty, "登录失败,请检查账号密码");
            return Page();
        }

        return Page();
    }
}

3. Next.js接收并使用JWT

Next.js端可通过服务端读取HttpOnly Cookie,或客户端读取非HttpOnly Cookie(不推荐),之后在API请求中携带token:

服务端读取示例(getServerSideProps):

export async function getServerSideProps(context) {
    const token = context.req.cookies.AuthToken;
    if (!token) {
        return {
            redirect: {
                destination: '/',
                permanent: false
            }
        };
    }

    return {
        props: { token }
    };
}

客户端API请求示例:

import axios from 'axios';

const apiClient = axios.create({
    baseURL: 'https://your-dotnet-api-domain.com/api',
});

// 请求拦截器自动添加token
apiClient.interceptors.request.use(config => {
    const token = document.cookie.split('; ').find(row => row.startsWith('AuthToken='))?.split('=')[1];
    if (token) {
        config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
});

// 调用受保护的API
export const fetchUserProfile = async () => {
    const response = await apiClient.get('/user/profile');
    return response.data;
};

4. 保护REST API端点

在.NET的API控制器中添加[Authorize]属性,确保只有携带有效JWT的请求能访问:

[ApiController]
[Route("api/[controller]")]
[Authorize]
public class UserController : ControllerBase
{
    [HttpGet("profile")]
    public IActionResult GetUserProfile()
    {
        // 从Claims中获取当前用户信息
        var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
        var email = User.FindFirstValue(ClaimTypes.Email);
        return Ok(new { UserId = userId, Email = email });
    }
}

注意事项

  • 跨域配置:如果Next.js和.NET项目不在同一域名,需在.NET项目中配置CORS:
    builder.Services.AddCors(options =>
    {
        options.AddPolicy("NextJsCors", policy =>
        {
            policy.WithOrigins("https://your-nextjs-domain.com")
                  .AllowAnyHeader()
                  .AllowAnyMethod()
                  .AllowCredentials(); // 允许携带Cookie
        });
    });
    
    // 中间件中启用CORS
    app.UseCors("NextJsCors");
    
  • JWT安全性:禁止在URL中传递token,优先使用HttpOnly Cookie;设置合理的token过期时间,并考虑实现刷新token机制。
  • 登录状态同步:用户在Razor Pages登出时,需清除AuthToken Cookie,确保Next.js端同步登出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 19:32:27