[英]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.