热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

wpf程序网络的影响_DotNetCoreWeb应用程序中的Cookie管理

原文来自互联网,由长沙DotNET技术社区编译。如译文侵犯您的署名权或版权,请联系小编,小编将在24小时内删除。限于译者的能力有限

8972e9e393dc368be3b123afca9af5f2.png

原文来自互联网,由长沙DotNET技术社区编译。如译文侵犯您的署名权或版权,请联系小编,小编将在24小时内删除。限于译者的能力有限,个别语句翻译略显生硬,还请见谅。

作者简介:Jon(Jonathan)Seeley,一位资深.NET开发者,主要从事Asp.NET/Asp.NET CORE/WPF等技术栈的开发,他的博客地址为https://www.seeleycoder.com/。

原文链接[1]

对于那些习惯于在传统ASP.NET中使用COOKIE的人来说,改用ASP.NET Core可能会让我们抓狂。在旧系统中,我们能够直接从请求和响应对象中添加和删除COOKIE(无论好坏)。这可能导致我们在请求期间多次写入和覆盖相同的COOKIE,因为不同部分的代码会影响它。DotNetCore改变了游戏规则,这是一件好事,相信我。今天,我们将学习DotNetCore Web应用程序中的COOKIE管理技术。

这篇文章的所有代码都可以在我的GitHub上找到[2]

了解过去

为了论证,我想介绍一下传统的ASP.NET MVC中用于加载COOKIE的“通用”代码。当然,问题在于,如果代码中的某处设置了COOKIE值,而我们稍后又在寻找它,我们想确保我们始终获得最新的副本,而不必一定是请求中包含的内容。下面的代码看起来是否响应中首先匹配。

public static System.Web.HttpCOOKIE GetCOOKIE(this System.Web.HttpContextBase context, string keyName){ System.Web.HttpCOOKIECollection COOKIEs = new System.Web.HttpCOOKIECollection(); System.Web.HttpCOOKIE COOKIE = null; // check for response value first... if (context.Response.COOKIEs.AllKeys.Any(key => string.Equals(key, keyName, StringComparison.OrdinalIgnoreCase))) COOKIE = context.Response.COOKIEs.Get(keyName); else if (context.Request.COOKIEs.AllKeys.Any(key => string.Equals(key, keyName, StringComparison.OrdinalIgnoreCase))) COOKIE = context.Request.COOKIEs.Get(keyName); return COOKIE;}

因此,这就是我们可能访问COOKIE进行消费的方式,我们在修改过程中会不会无意中把这个流程搞乱了?我敢肯定,大家也许有很多方式,以下这是我可能做过的一个例子:

public static void SetCOOKIE(this System.Web.HttpContextBase context, string keyName, string value, DateTime? expiry = null){ if (context.Response.HeadersWritten) return; // a null value is equivalent to deletion if (value == null) { context.Request.COOKIEs.Remove(keyName); context.Response.COOKIEs.Add(new System.Web.HttpCOOKIE(keyName, "") { Expires = DateTime.Today.AddYears(-1) }); return; } System.Web.HttpCOOKIE newCOOKIE = new System.Web.HttpCOOKIE(keyName, value); if (expiry.HasValue) newCOOKIE.Expires = expiry.Value; context.Response.COOKIEs.Add(newCOOKIE);}

在上面的代码中,我们试图确保删除COOKIE也可以防止在未找到同一请求的情况下尝试使用它。如果已经发送了标头,我们也将阻止编写COOKIE(因为它将引发异常)。该代码“不做”的一件事是防止重复,我是故意这样做的。一旦将其写到浏览器中,响应中的最后一个将调用,因此它仍将按预期“工作”,但同样,我们还有一个错误。如果您想知道,您不想随意,context.Response.COOKIEs.Add但是应该检查它是否已经存在,如果存在,请调用context.Response.SetCOOKIE。

尽管编写一个COOKIE管理器并确保您所有的COOKIE代码都能通过它并不困难,但对于菜鸟和经验丰富的开发人员来说,普遍认为“它可以正常工作”是很常见的。从这个角度来说,如果您确实了解了Asp.NET中COOKIE的设置方法并习惯了它,DotNetCore会让您失望。

DotNetCore的差异

既然我们已经介绍了一些您可能期望在传统的ASP.NET MVC中执行操作的方式,那么强调DotNetCore中的差异非常重要。

首先,HttpContext.Request.COOKIEsDotNetCore中的集合不能被修改。希望您在以前的示例中注意到,当我们删除传统版本的COOKIE时,我们也删除了请求副本,以确保以后不再使用无效的COOKIE。同样,HttpContext.Response.COOKIEs不允许您删除附加到该项目的项目。当然,您可以要求“删除” COOKIE,但这只是修改了到期时间,因此浏览器将其删除。一旦请求来了,就会调用这个方法。

当我用DotNetCore重写大型应用程序并从旧系统“复制”代码时,这些差异是我很早就遇到的,并导致了对ASP.NET Core中COOKIE管理的了解。

这些差异是一件好事,因为它们迫使您对正在做的事情多加思考,而不是仅仅假设一切正常。如果使用传统ASP.NET MVC的示例代码来设置COOKIE,除非小心,否则最终可能会在响应中获得COOKIE的多个副本。

如果发生这种情况,并且您稍后尝试在同一请求中读取该值,则可能实际上并没有获得您希望的结果。这样的操作很糟糕。

介绍COOKIE Service

鉴于我们之间的差异,再加上DotNetCore确实尽力让您使用依赖项注入这一事实,那么您将如何进行COOKIE管理?我个人认为,您所有的COOKIE管理都应通过服务进行分配,然后由中间件负责将最终状态写回到响应中。让我们开始吧:

public class CachedCOOKIE{ public string Name { get; set; } public string Value { get; set; } public COOKIEOptions Options { get; set; } public bool IsDeleted { get; set; }}public interface ICOOKIEService{ void Delete(string COOKIEName); T Get(string COOKIEName, bool isBase64 = false) where T : class; T GetOrSet(string COOKIEName, Func setFunc, DateTimeOffset? expiry = null, bool isBase64 = false) where T : class; void Set(string COOKIEName, T data, DateTimeOffset? expiry = null, bool base64Encode = false) where T : class; void WriteToResponse(HttpContext context);}public class COOKIEService : ICOOKIEService{ private readonly HttpContext _httpContext; private Dictionary _pendingCOOKIEs = null; public COOKIEService(IHttpContextAccessor httpContextAccessor) { _httpContext = httpContextAccessor.HttpContext; _pendingCOOKIEs = new Dictionary(); } public void Delete(string COOKIEName) { } public T Get(string COOKIEName, bool isBase64 = false) where T : class { throw new NotImplementedException(); } public T GetOrSet(string COOKIEName, Func setFunc, DateTimeOffset? expiry = null, bool isBase64 = false) where T : class { throw new NotImplementedException(); } public void Set(string COOKIEName, T data, DateTimeOffset? expiry = null, bool base64Encode = false) where T : class { } public void WriteToResponse(HttpContext context) { }}

在上面的代码块中,我添加了一个CachedCOOKIE类, 对我们的接口进行了存根COOKIEService,并为我们的服务设置了框架。

我们早应了解的一件事是,由于某种原因,该服务基于泛型。我希望能够将几乎所有的价值写到我的COOKIE中。在这种情况下,我选择将泛型限制在一个类中(该类string可以限定,但所有基本值类型都将失败)。为了使这种魔术起作用,我将使用JSON将我的值序列化为字符串。

为了弄清楚所有部分如何组合在一起,我认为我们将一次迈出这一步。

我们的构造函数正在注入,IHttpContextAccessor这使我们能够访问HttpContext请求的当前值。这类似于我们曾经使用过的旧ASP.NET HttpContext.Current。但是,要使此方法起作用,我们需要将其注册,因此请跳至Startup.cs您的ConfigureServices方法并将这些行添加到您的方法中:

services.AddSingleton();

services.AddScoped();

您还会在构造函数中注意到的另一件事是,我们正在为的实例设置一个空字典CachedCOOKIE。在中间件将它们转储到响应之前,这是我们在请求期间跟踪COOKIE状态的地方。

中间件

我们需要照顾的下一件事是创建我们的中间件并将其放入我们的管道中。让我们添加COOKIEServiceMiddleware.cs并编写下列代码:

internal class COOKIEServiceMiddleware{ private readonly RequestDelegate _next; public COOKIEServiceMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context, ICOOKIEService COOKIEService) { // write COOKIEs to response right before it starts writing out from MVC/api responses... context.Response.OnStarting(() => { // COOKIE service should not write out COOKIEs on 500, possibly others as well if (!context.Response.StatusCode.IsInRange(500, 599)) { COOKIEService.WriteToResponse(context); } return Task.CompletedTask; }); await _next(context); }}

无法在构造函数级别将范围服务注入中间件。您会注意到,我在Invoke方法中[3]注入了它,这似乎有点像魔术。在DotNetCore底层的某个地方的IServiceProvider组件知道如何进行注入。要注意的另一件事是,我检测到响应何时开始,然后检查状态码是否不在特定范围内。如果超出该范围,那么我们将继续通过服务将COOKIE写入响应中。该IsInRange扩展方法是一个我已经添加的话,事不宜迟,这里是一个基本的IntExtensions.cs添加到项目中我:

public static class IntExtensions{ public static bool IsInRange(this int checkVal, int value1, int value2) { // First check to see if the passed in values are in order. If so, then check to see if checkVal is between them if (value1 <&#61; value2) return checkVal >&#61; value1 && checkVal <&#61; value2; // Otherwise invert them and check the checkVal to see if it is between them return checkVal >&#61; value2 && checkVal <&#61; value1; }}

注册中间件

好的 最后&#xff0c;我们需要添加到中间件代码中并进行连接。中间件的约定是创建一个静态类和扩展方法来处理中间件的注册。让我们添加COOKIEServiceMiddlewareExtensions&#xff1a;

public static class COOKIEServiceMiddlewareExtensions{ public static IApplicationBuilder UseCOOKIEService(this IApplicationBuilder builder) { return builder.UseMiddleware(); }}

让我们进入Startup.cs进入我们的Configure方法中&#xff0c;并添加app.UseCOOKIEService();到链的某处。这里的窍门是您希望它在您的app.UseMvc呼叫之前以及可能影响您响应的任何其他内容之前显示&#xff0c;但不要太高以至于过早地向响应写出COOKIE。在这种情况下&#xff0c;我选择在app.UseCOOKIEPolicy通话后添加它。如果您有很多其他中间件&#xff0c;则您自己的工作量可能会有所不同。补充一下。如果我的中间件稍微复杂一点&#xff0c;并且有多个服务需要注册&#xff0c;那么我可能还创建了一个扩展方法来从我的ConfigureServices方法中调用。如果我正在创建一个用于分发的中间件&#xff0c;那么即使只有一个服务&#xff0c;我也绝对可以做到。我不想强迫某人必须了解一切&#xff0c;才能为DI配置我的中间件&#xff0c;他们应该能够简单地要求添加它并继续前进。

该扩展方法可能具有这样的签名public static IServiceCollection ConfigureCOOKIEService(this IServiceCollection services, IConfiguration configuration)。(这里的IConfiguration是可选的……在某些方面我需要它&#xff0c;但是显然在这种情况下我们不需要它)。

实现

太好了&#xff0c;我们现在已经注册了我们的服务和中间件&#xff0c;但是它什么也没做。让我们继续&#xff0c;一次开始实现一种方法。由于我们实际上要尝试做的第一件事是加载COOKIE以供消费&#xff0c;也许我们应该从那里开始。进入COOKIEService.cs并将以下代码添加到public T Get方法中&#xff1a;

Get 

public T Get(string COOKIEName, bool isBase64 &#61; false) where T : class{ return ExceptionHandler.SwallowOnException(() &#61;> { // check local cache first... if (_pendingCOOKIEs.TryGetValue(COOKIEName, out CachedCOOKIE COOKIE)) { // don&#39;t retrieve a "deleted" COOKIE if (COOKIE.IsDeleted) return default(T); return isBase64 ? Newtonsoft.Json.JsonConvert.DeserializeObject(COOKIE.Value.FromBase64String()) : Newtonsoft.Json.JsonConvert.DeserializeObject(COOKIE.Value); } if (_httpContext.Request.COOKIEs.TryGetValue(COOKIEName, out string COOKIEValue)) return isBase64 ? Newtonsoft.Json.JsonConvert.DeserializeObject(COOKIEValue.FromBase64String()) : Newtonsoft.Json.JsonConvert.DeserializeObject(COOKIEValue); return default(T); });}

在讨论之前&#xff0c;让我们先看一下这些内容ExceptionHandler。我们的Get方法首先询问我们的pendingCOOKIEs字典是否有与键匹配的东西。如果有&#xff0c;它将询问我们是否已对其进行标记IsDeleted。如果我们有一个并且未被删除&#xff0c;那么我们继续将其反序列化为请求的对象类型&#xff0c;并且可选地&#xff0c;我们需要首先从base64对其进行解码。如果我们在缓存中没有它的本地副本&#xff0c;那么我们继续看是否HttpContext.Request.COOKIEs具有它&#xff0c;并且像我们的本地缓存一样&#xff0c;可以选择在最终反序列化之前从base64解码。

现在&#xff0c;为什么我要对它进行base64编码&#xff1f;从本质上讲&#xff0c;我并不是要“保护”我的COOKIE免受窥视&#xff0c;但是&#xff0c;如果我有一个非常复杂的对象&#xff0c;我要写出一个COOKIE&#xff0c;我想对其进行分解。对象的JSON字符串表示形式可能非常笨拙。

说到base64编码…这些是我在StringExtensions.cs文件中添加的几个扩展方法。干得好&#xff1a;

public static class StringExtensions{ public static string FromBase64String(this string value, bool throwException &#61; true) { try { byte[] decodedBytes &#61; System.Convert.FromBase64String(value); string decoded &#61; System.Text.Encoding.UTF8.GetString(decodedBytes); return decoded; } catch (Exception ex) { if (throwException) throw new Exception(ex.Message, ex); else return value; } } public static string ToBase64String(this string value) { byte[] bytes &#61; System.Text.ASCIIEncoding.UTF8.GetBytes(value); string encoded &#61; System.Convert.ToBase64String(bytes); return encoded; }}

好吧&#xff0c;这是什么ExceptionHandler.SwallowOnException法术&#xff1f;我本可以使用该try {} catch {}块&#xff0c;但这是一个用例&#xff0c;其中我100&#xff05;可以接受&#xff0c;失败只是因为存在COOKIE而已&#xff0c;因为COOKIE根本就不存在。现在……如果您深入研究该处理程序的代码&#xff0c;您会发现它仍在执行try / catch块&#xff0c;我只是对其进行了抽象。让我向您证明这一点。

异常处理程序

public static class ExceptionHandler{ public static T SwallowOnException(Func func) { try { return func(); } catch { return default(T); } }}

Set

嘿&#xff0c;我们很酷&#xff0c;可以加载COOKIE&#xff0c;但是如果我们不能创建COOKIE&#xff0c;那不是很有用&#xff0c;对吧&#xff1f;让那部分起作用。

public void Set(string COOKIEName, T data, DateTimeOffset? expiry &#61; null, bool base64Encode &#61; false) where T : class{ // info about COOKIEoptions COOKIEOptions options &#61; new COOKIEOptions() { Secure &#61; _httpContext.Request.IsHttps }; if (expiry.HasValue) options.Expires &#61; expiry.Value; if (!_pendingCOOKIEs.TryGetValue(COOKIEName, out CachedCOOKIE COOKIE)) COOKIE &#61; Add(COOKIEName); // always set options and value; COOKIE.Options &#61; options; COOKIE.Value &#61; base64Encode ? Newtonsoft.Json.JsonConvert.SerializeObject(data).ToBase64String() : Newtonsoft.Json.JsonConvert.SerializeObject(data);}

创建COOKIE时&#xff0c;我们需要设置一些信息。我在这里几乎没有内容&#xff0c;但我强烈建议您阅读COOKIEOptions[4]。不设置Expires将默认为“会话” COOKIE。如果您将Google Chrome浏览器用于“始终打开”模式(或所谓的“笨拙”)&#xff0c;则它们将无法正常工作。在这里的代码中&#xff0c;我们将查看是否已经有一个待处理的COOKIE实例&#xff0c;如果没有&#xff0c;则添加一个实例。一分钟后&#xff0c;我将介绍该方法。在获得COOKIE实例之后&#xff0c;我们将附加选项并编写可选的以base64编码的值。Add现在让我们看一下该方法。

protected CachedCOOKIE Add(string COOKIEName){ var COOKIE &#61; new CachedCOOKIE { Name &#61; COOKIEName }; _pendingCOOKIEs.Add(COOKIEName, COOKIE); return COOKIE;}

很基本的东西。我们只是放宽信任&#xff0c;我们可以添加它并添加它。该方法没有公开&#xff0c;所以我相信我不必先检查字典。如果您对此不满意&#xff0c;请随时进行修改。

删除COOKIE

在某个时候&#xff0c;我们将要删除COOKIE&#xff0c;对吗&#xff1f;我们希望确保对同一COOKIE的后续查询都知道它已被删除&#xff0c;正如我们在Get调用中所看到的那样。为了使它正常工作&#xff0c;我们需要本地缓存来跟踪它。

void ICOOKIEService.Delete(string COOKIEName){ Delete(COOKIEName);}protected CachedCOOKIE Delete(string COOKIEName){ if (_pendingCOOKIEs.TryGetValue(COOKIEName, out CachedCOOKIE COOKIE)) COOKIE.IsDeleted &#61; true; else { COOKIE &#61; new CachedCOOKIE { Name &#61; COOKIEName, IsDeleted &#61; true }; _pendingCOOKIEs.Add(COOKIEName, COOKIE); } return COOKIE;}

在上面的代码中&#xff0c;我们具有接口Delete方法和类Delete方法&#xff0c;它们都具有相同的签名。我可以给他们起个不同的名字&#xff0c;但我真的不想这么做。但是&#xff0c;为了防止编译器报错&#xff0c;我们必须将接口方法设为显式接口调用。我们只需将该调用传递到我们的类实例方法中。进入类实例delete方法后&#xff0c;我们将查看是否已经有一个暂挂实例&#xff0c;如果有&#xff0c;请将其标记为已删除。如果没有&#xff0c;我们将其添加到缓存中并标记为已删除。

GetOrSet 

有时&#xff0c;您希望COOKIE不管存在如何&#xff0c;但是如果已经存在&#xff0c;那么您就想获得它的价值。一个用例是如果您要加载COOKIE(如果存在)或设置默认值。在我工作过的一个站点上&#xff0c;我们有一个适合该用例的“行程计划器”。我想知道他们的详细信息(如果有的话)&#xff0c;否则我将设置一些默认值&#xff0c;以便其余的会话体验基于相同的信息。设置非常简单&#xff1a;

public T GetOrSet(string COOKIEName, Func setFunc, DateTimeOffset? expiry &#61; null, bool isBase64 &#61; false) where T : class{ T COOKIE &#61; Get(COOKIEName, isBase64); if (COOKIE !&#61; null) return COOKIE; T data &#61; setFunc(); Set(COOKIEName, data, expiry, isBase64); return data;}

如果COOKIE存在&#xff0c;我们得到它。如果没有&#xff0c;我们将其设置。十分简单。

输出

如果我们从不将其写回响应中&#xff0c;那么以上所有代码实际上都没有关系&#xff0c;对吗&#xff1f;还记得在context.Response.OnStarting我们告诉服务期间在中间件中执行的服务WriteToResponse吗&#xff1f;让我们现在实际做点什么&#xff1a;

public void WriteToResponse(HttpContext context){ foreach (var COOKIE in _pendingCOOKIEs.Values) { if (COOKIE.IsDeleted) context.Response.COOKIEs.Delete(COOKIE.Name); else context.Response.COOKIEs.Append(COOKIE.Name, COOKIE.Value, COOKIE.Options); }}

我们重复我们的每一个悬而未决的饼干和要么Delete或者Append他们根据我们的缓存值。现在我们只写出每个COOKIE的一个副本&#xff0c;而不是我们在本文开头介绍的经典ASP.NET崩溃。

与测试代码一起实现

GitHub上的代码在HomeController中有一个相当蹩脚的小演示。接下来是一些单元测试。在发布一些代码之前&#xff0c;我想回顾一下我的BaseTest.cs工作方式。我可以(坦率地说应该有)&#xff0c;但是由于我从生产代码中复制了这个代码&#xff0c;而这个代码还有其他问题&#xff0c;所以我没有使用)DotNetCore服务集合。相反&#xff0c;BaseTest依赖于UnityContainer。对于我而言&#xff0c;这是设置依赖项引擎的一种非常简单的方法。你想怎么嘲笑就怎么嘲笑吧。

随之而来的将是COOKIEServiceTests类的一大堆垃圾。该Initialize方法设置了每个测试将要使用的内容&#xff0c;然后每个单独的测试都设置了自己的场景。如何使用该服务应该变得显而易见&#xff0c;并希望为您提供一些如何在自己的项目中使用该服务的想法。

[TestClass]public class COOKIEServiceTests : BaseTest{ IHttpContextAccessor _httpContextAccessor; HttpContext _httpContext; COOKIEService _target; [TestInitialize] public void Initialize() { _httpContextAccessor &#61; Substitute.For(); _httpContext &#61; new DefaultHttpContext(); _httpContextAccessor.HttpContext.Returns(_httpContext); Container.RegisterInstance(_httpContextAccessor); _target &#61; Container.Resolve(); } [TestMethod] public void COOKIEService_SetCOOKIE_Success() { COOKIEFake COOKIE &#61; new COOKIEFake { TestProperty &#61; 25, TestPropertyString &#61; "blah" }; _target.Set("fakeCOOKIE", COOKIE); COOKIEFake cachedCOOKIE &#61; _target.Get("fakeCOOKIE"); Assert.IsNotNull(cachedCOOKIE); Assert.AreEqual(COOKIE.TestProperty, cachedCOOKIE.TestProperty); Assert.AreEqual(COOKIE.TestPropertyString, cachedCOOKIE.TestPropertyString); } [TestMethod] public void COOKIEService_SetCOOKIE_StringOnly_Success() { string value &#61; "I&#39;m a COOKIE value"; _target.Set("fakeCOOKIE", value); string result &#61; _target.Get("fakeCOOKIE"); Assert.IsFalse(string.IsNullOrWhiteSpace(result)); Assert.AreEqual(value, result); } [TestMethod] public void COOKIEService_SetCOOKIE_Base64_Success() { COOKIEFake COOKIE &#61; new COOKIEFake { TestProperty &#61; 25, TestPropertyString &#61; "blah" }; _target.Set("fakeCOOKIE", COOKIE, base64Encode: true); COOKIEFake cachedCOOKIE &#61; _target.Get("fakeCOOKIE", true); Assert.IsNotNull(cachedCOOKIE); Assert.AreEqual(COOKIE.TestProperty, cachedCOOKIE.TestProperty); Assert.AreEqual(COOKIE.TestPropertyString, cachedCOOKIE.TestPropertyString); } [TestMethod] public void COOKIEService_GetOrSetCOOKIE_SetsCOOKIE_Success() { Func createCOOKIE &#61; () &#61;> { return new COOKIEFake { TestProperty &#61; 25, TestPropertyString &#61; "blah" }; }; var COOKIE &#61; _target.GetOrSet("fakeCOOKIE", createCOOKIE); Assert.IsNotNull(COOKIE); Assert.AreEqual(COOKIE.TestProperty, 25); } [TestMethod] public void COOKIEService_GetOrSetCOOKIE_GetsCOOKIE_Success() { COOKIEFake COOKIE &#61; new COOKIEFake { TestProperty &#61; 25, TestPropertyString &#61; "blah" }; _target.Set("fakeCOOKIE", COOKIE); Func createCOOKIE &#61; () &#61;> { return new COOKIEFake { TestProperty &#61; 55, TestPropertyString &#61; "blah2" }; }; var retrievedCOOKIE &#61; _target.GetOrSet("fakeCOOKIE", createCOOKIE); Assert.IsNotNull(retrievedCOOKIE); Assert.AreEqual(retrievedCOOKIE.TestProperty, COOKIE.TestProperty); Assert.AreEqual(retrievedCOOKIE.TestPropertyString, COOKIE.TestPropertyString); } [TestMethod] public void COOKIEService_GetCOOKIE_Fail() { COOKIEFake cachedCOOKIE &#61; _target.Get("fakeCOOKIE"); Assert.IsNull(cachedCOOKIE); } [TestMethod] public void COOKIEService_GetCOOKIE_Base64_Fail() { COOKIEFake COOKIE &#61; new COOKIEFake { TestProperty &#61; 25, TestPropertyString &#61; "blah" }; _target.Set("fakeCOOKIE", COOKIE); COOKIEFake cachedCOOKIE &#61; _target.Get("fakeCOOKIE", true); Assert.IsNull(cachedCOOKIE); }}public class COOKIEFake{ public int TestProperty { get; set; } public string TestPropertyString { get; set; }}

结论

DotNetCore Web应用程序中的COOKIE管理并不是一件复杂的事情&#xff0c;但是很容易使效率低下。我们通过引入COOKIEService和中间件&#xff0c;研究了一种确保响应尽可能干净的方法。

今天发布的所有代码都可以在我的GitHub上找到[5]

我鼓励您查看整个项目&#xff0c;查看我在Web应用程序中蹩脚的示例&#xff0c;我相信你能从中学到有用的知识。

References

[1] 原文链接: https://www.seeleycoder.com/blog/COOKIE-management-asp-net-core/[2] 我的GitHub上找到: https://github.com/fooberichu150/COOKIEService[3] Invoke方法中: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view&#61;aspnetcore-2.1#service-lifetimes[4] 您阅读COOKIEOptions: https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.COOKIEoptions?view&#61;aspnetcore-2.1[5] 我的GitHub上找到: https://github.com/fooberichu150/COOKIEService



推荐阅读
  • 本文讨论了在ASP中创建RazorFunctions.cshtml文件时出现的问题,即ASP.global_asax不存在于命名空间ASP中。文章提供了解决该问题的代码示例,并详细解释了代码中涉及的关键概念,如HttpContext、Request和RouteData等。通过阅读本文,读者可以了解如何解决该问题并理解相关的ASP概念。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • 开发笔记:Java是如何读取和写入浏览器Cookies的
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java是如何读取和写入浏览器Cookies的相关的知识,希望对你有一定的参考价值。首先我 ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • 本文介绍了ASP.NET Core MVC的入门及基础使用教程,根据微软的文档学习,建议阅读英文文档以便更好理解,微软的工具化使用方便且开发速度快。通过vs2017新建项目,可以创建一个基础的ASP.NET网站,也可以实现动态网站开发。ASP.NET MVC框架及其工具简化了开发过程,包括建立业务的数据模型和控制器等步骤。 ... [详细]
  • MVC中的自定义控件
    怎么样创建自定义控 ... [详细]
  • 我将SpringMVC升级到Spring3.2.5.我的一些剩余调用即使存在,也会返回无法识别的字段异常.这是错误.Resolvingexceptionfrom ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • IOS开发之短信发送与拨打电话的方法详解
    本文详细介绍了在IOS开发中实现短信发送和拨打电话的两种方式,一种是使用系统底层发送,虽然无法自定义短信内容和返回原应用,但是简单方便;另一种是使用第三方框架发送,需要导入MessageUI头文件,并遵守MFMessageComposeViewControllerDelegate协议,可以实现自定义短信内容和返回原应用的功能。 ... [详细]
  • Asp.net Mvc Framework 七 (Filter及其执行顺序) 的应用示例
    本文介绍了在Asp.net Mvc中应用Filter功能进行登录判断、用户权限控制、输出缓存、防盗链、防蜘蛛、本地化设置等操作的示例,并解释了Filter的执行顺序。通过示例代码,详细说明了如何使用Filter来实现这些功能。 ... [详细]
  • 本文讨论了在shiro java配置中加入Shiro listener后启动失败的问题。作者引入了一系列jar包,并在web.xml中配置了相关内容,但启动后却无法正常运行。文章提供了具体引入的jar包和web.xml的配置内容,并指出可能的错误原因。该问题可能与jar包版本不兼容、web.xml配置错误等有关。 ... [详细]
  • XMLhttpREquest_Ajax技术总结之XmlHttpRequest
    Ajax1、 什么是ajax   ... [详细]
author-avatar
zf19920222
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有