在 Blazor 服务器端创建和读取 Cookie

问题描述 投票:0回答:6

在 Blazor 服务器端创建和读取 cookie 的最简单方法是什么。
似乎所有的解决方案都是针对 Blazor Web 组件的,每当我使用这些解决方案时,Response.Cookies.Append("") 和 Request.Cookies[] 选项都不起作用。

c# asp.net-core cookies blazor-server-side
6个回答
13
投票

wwwroot/index.html
(Blazor WebAssembly) 或
Pages/_Host.cshtml
(Blazor Server) 内,编写以下 javascript 代码:

  <script>
    window.WriteCookie = {

        WriteCookie: function (name, value, days) {

            var expires;
            if (days) {
                var date = new Date();
                date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
                expires = "; expires=" + date.toGMTString();
            }
            else {
                expires = "";
            }
            document.cookie = name + "=" + value + expires + "; path=/";
        }
    }
    window.ReadCookie = {
        ReadCookie: function (cname) {
        var name = cname + "=";
        var decodedCookie = decodeURIComponent(document.cookie);
        var ca = decodedCookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == ' ') {
                c = c.substring(1);
            }
            if (c.indexOf(name) == 0) {
                return c.substring(name.length, c.length);
            }
        }
        return "";
    }
}
</script>

然后,将以下示例代码写入 Razor 组件(.razor):

@inject IJSRuntime JsRuntime;
<button class="btn" @onclick="WriteCookies">
    Write Cookie
</button>
<button class="btn" @onclick="ReadCookies">
    Read Cookie
</button>

<p>The cookie is @myCookieValue</p>
@code {
    public string myCookieValue { get; set; } = "";
    protected async Task WriteCookies()
    {

        await JsRuntime.InvokeAsync<object>("WriteCookie.WriteCookie", "cookieName", "cookieValue", DateTime.Now.AddMinutes(1));

    }
    protected async Task ReadCookies()
    {

        myCookieValue= await JsRuntime.InvokeAsync<string>("ReadCookie.ReadCookie", "cookieName");

    }

}

9
投票

如果您想从 Blazor 组件访问 Cookie,您需要注入 IHttpContextAccessor 如下所示

[Inject]
IHttpContextAccessor HttpContextAccessor { get; set; }

然后您可以使用注入的 HttpContextAccessor 从 Request 对象访问 Cookies

var token = httpContextAccessor.HttpContext.Request.Cookies["access_token"];

要设置访问令牌,请使用:

CookieOptions options = new CookieOptions();
options.Expires = DateTime.Now.AddDays(1);
httpContextAccessor.HttpContext.Response.Cookies.Append("access_token", response.access_token, options);

如果您想从服务访问 Cookie,那么您需要在服务的构造函数中使用依赖注入添加 IHttpContextAccessor,如下所示:

public AccessoryService(HttpClient httpClient,
    IHttpContextAccessor HttpContextAccessor)
{
    this.httpClient = httpClient;
    httpContextAccessor = HttpContextAccessor;
}

请在启动时添加 services.AddHttpContextAccessor(); 以进行依赖注入。

最后你可以使用从 Request 对象检索到的令牌来调用 api:

public async Task<IEnumerable<AccessoryDto>> GetAccessories()
{
    var token = httpContextAccessor.HttpContext.Request.Cookies["access_token"];
    httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer",token);

    var accessories = await httpClient.GetFromJsonAsync<AccessoryDto[]>("api/accessory");
    return accessories;
}

5
投票

我找到了使用本地存储解决 Blazor 服务器端 Cookie 问题的绝佳解决方案。

首先,使用以下命令获取 NuGet Blazored LocalStorage

Install-Package Blazored.LocalStorage

我必须更新我的 System.Text.Json,请从 https://www.nuget.org/packages/System.Text.Json/

执行此操作

将以下内容添加到 Startup.cs 中:

public void ConfigureServices(IServiceCollection services)
{
    services.AddBlazoredLocalStorage();   // local storage
    services.AddBlazoredLocalStorage(config =>
        config.JsonSerializerOptions.WriteIndented = true);  // local storage
}

或者在最新的.NET版本中

using Blazored.LocalSorage;
var builder = WebApplication.CreateBuilder(args);
// add after builder initialization:
builder.Services.AddBlazoredLocalStorage();   // local storage
builder.Services.AddBlazoredLocalStorage(config => config.JsonSerializerOptions.WriteIndented = true);  // local storage

在您的 Razor 页面上(我使用 Index.razor 进行测试):

@page "/"
@inject Blazored.LocalStorage.ILocalStorageService localStorage

<button @onclick="HandleSubmit">Create Cookie</button>  @* Create your cookie *@

@code{
    public async Task HandleSubmit()
    {
        await localStorage.SetItemAsync("cookieName", "Jason Bourne");
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        var cookieContent = await localStorage.GetItemAsync<string>("cookieName");

        if (cookieContent == null)
        {
            Console.WriteLine("Cookie is blank");
        }
        else
        {
            Console.WriteLine("We have a cookie with contents: " + cookieContent);
        }
    }
}

2
投票

无意冒犯其他人,但这些答案可能比您需要的更复杂。

您可以使用 JavaScript Interop 在客户端执行任何您想要的操作。 这样,您就可以直接控制一切,而不是依赖库或插件。


0
投票

使用上述所有示例。我想出了这个

Javascript

const Empty = '';

window.Cookie = {
    Read: function () {
        return (document.cookie == Empty) ? '[name]=[value]' : decodeURIComponent(document.cookie);
    },
    Write: function (name, value, days) {
        document.cookie = name + '=' + value + this.ExpireOn(days) + ';path=/';
    },
    ExpireOn: function (days) {
        return Number.isFinite(days) ? ';expires=' + new Date().AddDay(days).toGMTString() : Empty;
    }
}
Date.prototype.AddDay = function(days) {
    this.setDate(this.getDate() + days);
    return this;
}

添加cookie.cs

namespace Blazor;
public class Cookie
{
    private IDictionary<string, string> _values;
    private readonly IJSRuntime _js;
    public Cookie(IJSRuntime js) => _js = js;
    public async Task<string> Get(string name) => (await Read()).TryGetValue(name, out var val) ? val : string.Empty;
    public async Task Set(string name, string val, int? days = null)
    {
        await Write(name, val, days);
        (await Read()).UpSert(name, val);
    }
    private async Task<IDictionary<string, string>> Read() =>
        _values ??= (await _js.InvokeAsync<string>(COOKIE.READ))
                    .Split(STR.SEMICOLON)
                    .Select(nv => nv.Split(STR.EQUAL))
                    .ToDictionary(nv => nv.First().Trim(), nv => nv.Last().Trim());
    private async Task Write(string name, string val, int? days) => await _js.InvokeAsync<string>(COOKIE.WRITE, name, val, days);
}

添加范围

services.AddScoped<Cookie>();

将 Cookie 注入组件并在 OnAfterRenderAsync 中使用它。示例

    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        if (!firstRender)
            return;

        var val = await Cookie.Get(COOKIE.LANG.NAME);
        _selectedValue = string.IsNullOrEmpty(val) ? Cache.DefaultLang : val;

       _mudSelect?.SelectedValuesChanged.InvokeAsync();
   }
  

此方法可与本地存储或会话存储一起使用。您只需要编写最少的 JavaScript 即可在客户端读取/写入它,并在服务器端编写一个包装器。 Cookie.cs 可以注入任何组件并用作用户数据会话存储。

IHttpContext Accessor 不是 Blazor 方式。任何客户端都应该可以通过 IJSRuntime 访问。


0
投票

在我看来,在 Blazor 服务器端中读取 cookie 的最简单方法是 HttpContextAccessor,但写入 的最简单方法是 Javascript:

@inject IHttpContextAccessor httpContext
@inject IJSRuntime jsRuntime


var myCookie= httpContext.HttpContext
 .Request.Cookies.FirstOrDefault(c=>c.Name=="myCookieName");

jsRuntime.InvokeVoidAsync(
 $"document.cookie=\"{myCookieName}={myStringifiedValue}; max-age={180}; path=/;\"");

© www.soinside.com 2019 - 2024. All rights reserved.