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

谷歌第三方登录后用户头像显示异常问题求助

问题说明

已实现登录页面及谷歌第三方登录功能,普通注册登录流程正常,用户登录后头像可正常显示。但谷歌登录存在异常:用户能完成登录,个人信息已存入数据库,但头像显示错误。

后端谷歌登录回调代码

[Route("google-response")]
public async Task<ActionResult> GoogleResponse()
{
    var google_csrf_name = "g_csrf_token";
    var cookie = Request.Cookies[google_csrf_name];
    if (cookie == null)
        return StatusCode((int)HttpStatusCode.BadRequest);

    var requestbody = Request.Form[google_csrf_name];

    if (requestbody != cookie)
        return StatusCode((int)HttpStatusCode.BadRequest);

    var idtoken = Request.Form["credential"];
    GoogleJsonWebSignature.Payload payload = await GoogleJsonWebSignature.ValidateAsync(idtoken).ConfigureAwait(false);

    byte[] y = System.Text.Encoding.UTF8.GetBytes(payload.Picture);

    var user = new ApplicationUser { UserName = payload.Email, Email = payload.Email , 
        firstName = payload.GivenName, lastName = payload.FamilyName, PictureSource = y, EmailConfirmed=true
    };
    await _userManager.CreateAsync(user).ConfigureAwait(false);
    await _signManager.SignInAsync(user, isPersistent: false).ConfigureAwait(false);
    return RedirectToAction("Index","Dashboard");
}

前端侧边栏代码

@* 根据登录状态切换 *@ 
@if (!SignInManager.IsSignedIn(User))
{
    <div class="profile-wrapper">
        <img class="profile-pic" src="~/profile.jpg" />
        <div class="titles d-flex flex-column ps-3">
            <h6 class="mb-0">Expense Tracher</h6>
            <span class="text-muted">Guest</span>
        </div>
    </div>
}
else
{
    <div class="profile-wrapper">
        <img style="width:40px;height:40px; object-fit:cover; border-radius:30px" src="data:image/*;base64,@(Convert.ToBase64String(UserManager.GetUserAsync(User)?.Result.PictureSource))">
        <div class="titles d-flex flex-column ps-3">
            <h6 class="mb-0">Expense Tracher</h6>
            <span class="text-muted">@User.Identity?.Name</span>
        </div>
    </div>
}

问题根源

代码错误地将谷歌返回的头像URL字符串直接转成UTF8字节数组存入数据库,而前端尝试将这个URL的字节数据解码为图片的base64格式,自然无法正确显示图片。

解决方案

修改后端代码,通过HTTP请求下载谷歌头像URL对应的图片二进制数据,再存入数据库:

[Route("google-response")]
public async Task<ActionResult> GoogleResponse()
{
    var google_csrf_name = "g_csrf_token";
    var cookie = Request.Cookies[google_csrf_name];
    if (cookie == null)
        return StatusCode((int)HttpStatusCode.BadRequest);

    var requestbody = Request.Form[google_csrf_name];
    if (requestbody != cookie)
        return StatusCode((int)HttpStatusCode.BadRequest);

    var idtoken = Request.Form["credential"];
    GoogleJsonWebSignature.Payload payload = await GoogleJsonWebSignature.ValidateAsync(idtoken).ConfigureAwait(false);

    byte[] imageBytes = null;
    // 下载谷歌头像图片
    if (!string.IsNullOrEmpty(payload.Picture))
    {
        using var httpClient = new HttpClient();
        try
        {
            imageBytes = await httpClient.GetByteArrayAsync(payload.Picture).ConfigureAwait(false);
        }
        catch (HttpRequestException)
        {
            // 图片下载失败时可设置默认头像字节,示例:读取项目内默认头像
            // imageBytes = await System.IO.File.ReadAllBytesAsync("wwwroot/profile.jpg").ConfigureAwait(false);
        }
    }

    var user = new ApplicationUser 
    { 
        UserName = payload.Email, 
        Email = payload.Email, 
        firstName = payload.GivenName, 
        lastName = payload.FamilyName, 
        PictureSource = imageBytes, 
        EmailConfirmed = true
    };
    await _userManager.CreateAsync(user).ConfigureAwait(false);
    await _signManager.SignInAsync(user, isPersistent: false).ConfigureAwait(false);
    return RedirectToAction("Index","Dashboard");
}

补充说明

  1. 生产环境建议注入IHttpClientFactory替代直接实例化HttpClient,避免套接字耗尽问题。
  2. 处理图片下载异常,设置默认头像可提升用户体验。
  3. 前端代码无需修改,只要PictureSource存储的是图片二进制数据,Convert.ToBase64String就能生成可正常显示的base64图片数据。

内容的提问来源于stack exchange,提问作者Rami Taher Wahdan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 18:25:55