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

ASP.NET Core 2第三方登录往返传递邀请密钥技术问询

实现Google登录时传递邀请密钥到用户创建流程

没问题,我来一步步帮你搞定这个需求——让Google登录时能把邀请密钥mykey传递到用户创建流程里,完全适配ASP.NET Core的默认身份架构。核心思路是利用ASP.NET Core身份验证的AuthenticationProperties存储邀请密钥,因为外部登录跳转(比如到Google授权页)时,这个对象会帮我们保留状态,避免参数丢失。下面是具体的代码修改步骤:

1. 修改ExternalLogin方法

这是用户点击Google登录链接时的入口,我们需要在这里把邀请密钥存到身份验证属性里,然后发起登录挑战:

public IActionResult ExternalLogin(string provider, string key, string returnUrl = null)
{
    // 先做个密钥有效性校验(非常推荐!防止恶意请求)
    if (!IsValidInvitationKey(key)) // 你需要自己实现这个校验方法,比如查数据库看密钥是否存在且未被使用
    {
        ModelState.AddModelError("", "无效的邀请密钥,请检查链接后重试");
        return RedirectToAction("Login");
    }

    // 配置身份验证属性,把邀请密钥存到Items字典里
    var authProperties = new AuthenticationProperties
    {
        // 指定授权完成后的回调地址
        RedirectUri = Url.Action("ExternalLoginCallback", new { returnUrl }),
        Items =
        {
            { "invitation_key", key }, // 把mykey存进去,后面回调时能取到
            { "returnUrl", returnUrl }
        }
    };

    // 发起外部登录挑战,带上我们配置好的属性
    return Challenge(authProperties, provider);
}

2. 在ExternalLoginCallback中传递密钥到确认页面

Google授权完成后会回调这个方法,我们需要从AuthenticationProperties里取出之前存的密钥,再传递给用户创建的确认页面:

public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
    // 处理错误情况
    if (remoteError != null)
    {
        ModelState.AddModelError("", $"授权出错: {remoteError}");
        return RedirectToAction("Login");
    }

    // 获取外部登录信息
    var loginInfo = await _signInManager.GetExternalLoginInfoAsync();
    if (loginInfo == null)
    {
        ModelState.AddModelError("", "无法加载外部登录信息");
        return RedirectToAction("Login");
    }

    // 从身份验证属性中取出邀请密钥
    var authResult = await HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme);
    var invitationKey = authResult.Properties.Items["invitation_key"];

    // 检查用户是否已存在,存在则直接登录
    var signInResult = await _signInManager.ExternalLoginSignInAsync(
        loginInfo.LoginProvider, 
        loginInfo.ProviderKey, 
        isPersistent: false, 
        bypassTwoFactor: true);

    if (signInResult.Succeeded)
    {
        // 用户已存在,这里可以根据密钥做后续处理(比如关联邀请记录)
        await MarkInvitationAsUsed(invitationKey); // 可选,标记密钥已使用
        return LocalRedirect(returnUrl ?? "/");
    }
    else if (signInResult.IsLockedOut)
    {
        return RedirectToAction("Lockout");
    }
    else
    {
        // 用户不存在,准备跳转到创建页面,把密钥传递过去
        var model = new ExternalLoginViewModel
        {
            Email = loginInfo.Principal.FindFirstValue(ClaimTypes.Email),
            InvitationKey = invitationKey // 把密钥放到ViewModel里
        };

        ViewData["ReturnUrl"] = returnUrl;
        return View("ExternalLoginConfirmation", model);
    }
}

3. 在ExternalLoginConfirmation中使用密钥创建用户

这一步是创建新用户的核心方法,我们可以直接从ViewModel中拿到密钥,用来关联邀请信息:

先给ViewModel添加密钥属性

首先要确保你的ExternalLoginViewModel包含InvitationKey字段:

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

    // 添加这个属性来接收邀请密钥
    public string InvitationKey { get; set; }
}

修改ExternalLoginConfirmation方法

public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginViewModel model, string returnUrl = null)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    // 获取外部登录信息
    var loginInfo = await _signInManager.GetExternalLoginInfoAsync();
    if (loginInfo == null)
    {
        throw new ApplicationException("创建用户时加载外部登录信息失败");
    }

    // 拿到传递过来的邀请密钥
    var invitationKey = model.InvitationKey;

    // 创建新用户,这里可以把密钥关联到用户实体(比如存到User表的InvitationKey字段)
    var newUser = new ApplicationUser
    {
        UserName = model.Email,
        Email = model.Email,
        InvitationKey = invitationKey // 关联密钥到用户
    };

    // 执行用户创建
    var createResult = await _userManager.CreateAsync(newUser);
    if (createResult.Succeeded)
    {
        // 关联外部登录信息到用户
        var addLoginResult = await _userManager.AddLoginAsync(newUser, loginInfo);
        if (addLoginResult.Succeeded)
        {
            // 标记邀请密钥已使用(可选)
            await MarkInvitationAsUsed(invitationKey);
            
            // 登录新用户
            await _signInManager.SignInAsync(newUser, isPersistent: false);
            return LocalRedirect(returnUrl ?? "/");
        }
        AddErrors(addLoginResult);
    }
    AddErrors(createResult);

    ViewData["ReturnUrl"] = returnUrl;
    return View(model);
}

最后补充:生成登录URL的格式

你需要生成类似这样的URL给用户(确保路由能正确解析provider和key参数):
https://localhost:44338/account/ExternalLogin?provider=Google&key=mykey
如果你的路由是自定义的(比如/account/login/{key}),记得调整路由模板,保证ExternalLogin方法能接收到provider和key参数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:28:35