繁体   English   中英

Blazor 服务器应用程序 - 无法设置 Cookie

[英]Blazor Server App - Cookie can not be set

我正在开发一个项目来演示授权代码流。 因此,我不想使用任何为我处理身份验证的库,但我想自己完成整个过程。 我创建了一个 Blazor 服务器应用 (SignalR)。 在索引页面上有一个“连接”按钮,它启动了整个身份验证过程,如下所示。

索引.razor

    //on button click
    protected async Task ConnectClick()
    {
        await ConnectService.Connect();
    }

连接服务.cs


        public void CreateSession()
        {
            if(!_httpContextAccessor.HttpContext.Request.Cookies.TryGetValue("userId", out string userId))
            {
                _httpContextAccessor.HttpContext.Response.Cookies.Append("userId", Guid.NewGuid().ToString());
            }
        }

        public async Task Connect()
        {
            CreateSession();
            //Generate random string as "state" parameter for ACF
            var state = Guid.NewGuid().ToString();

            var authorizeArgs = new Dictionary<string, string>
            {
                {"client_id", ...},
                {"scope", ...},
                {"redirect_uri", ".../Auth/ConnectCallback"},
                {"response_type", "code"},
                {"state", state}
            };

            //Save state to cookie to verify in later step
            _httpContextAccessor.HttpContext.Response.Cookies.Append("state", state);

            var url = ... //prepare url, not important
            _navigationManager.NavigateTo(url);
        }

        public async Task ConnectCallback(string code, string state)
        {
            //Verify state
            if(!_httpContextAccessor.HttpContext.Request.Cookies.TryGetValue("state", out string stateValue) || stateValue != state)
            {
                throw new AuthenticationException();
            }

            ... //rest of authentication steps

            _httpContextAccessor.HttpContext.Request.Cookies.TryGetValue("userId", out string userId);
            _memoryCache.Set(userId, access_token);
            _navigationManager.NavigateTo("/mypage");
        }

ConnectCallback.razor

    @page "/Auth/ConnectCallback"
    ...

    @code {

       protected override async Task OnInitializedAsync()
       {
          await AuthService.ConnectCallback(HttpContextAccessor.HttpContext.Request.Query["code"][0], HttpContextAccessor.HttpContext.Request.Query["state"][0]);
       }

我知道图书馆会以更简洁的方式处理这个问题,但目标是在一个小型演示应用程序中显示流程。

这是最新的状态。 我不知道将访问令牌直接保存在浏览器中是否更好,但现在我将它与 userId 配对保存在内存中。

在这种情况下发生的情况是,每当我尝试附加一个我会收到的 cookie 时:

System.InvalidOperationException: Headers are read-only, response has already started.

现在,我明白我做错了什么。 有谁知道正确的方法是什么,或者我在这里做错了什么? 我似乎在任何地方都找不到任何解决方案。

您可以创建一个用于 cookie 管理的CookieController并重定向到它。 IsEssential表示该 cookie 是网站正常运行所必需的。

[Route("[controller]")]
[ApiController]
public class CookieController : ControllerBase
{
  [HttpGet("SetStateCookie")]
  public async Task<ActionResult> SetStateCookie()
  {
    CookieOptions opt = new CookieOptions
    {
      IsEssential = true
    };
    Response.Cookies.Append("state", $"{Guid.NewGuid()}", opt);
    return Redirect("/");
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM