[转]Session and application state in ASP.NET Core
2017-02-04 11:21
696 查看
本文转自:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state
By Rick Anderson and Steve Smith+
HTTP is a stateless protocol; the Web server treats each HTTP request as an independent request. The server retains no knowledge of variable values that were used in previous requests. This article discusses various approaches to preserving application and user (session) state between requests. +
Application state, unlike session state, applies to all users and sessions.+
Session is retained by the server for a limited time after the last request. The default session timeout is 20 minutes, but you can configure session time out. The session data is backed by a cache. Session is ideal for storing user state that is specific to a particular session but which doesn’t need to be persisted permanently. Data is deleted from the backing store either when you call
Warning
Sensitive data should never be stored in session. You can’t guarantee the client will close the browser and clear their session cookie (and some browsers keep them alive across windows). Consequently, you can’t assume that a session is restricted to a single user, the next user may continue with the same session.+
The in-memory session provider stores session data on the server, which can impact scale out. If you run your web app on a server farm, you’ll need to enable sticky sessions to tie each session to a specific server. Windows Azure Web Sites defaults to sticky sessions (Application Request Routing or ARR). Sticky session can impact scalability and complicate updating your web app. The Redis and SQL Server distributed caches don't require sticky sessions and are the preferred approach to multi-server caching. See Working with a Distributed Cache for more information.+
See Configuring Session below for more details.+
Copy
C#
The cookie-based TempData provider does not use Session; data is stored in a cookie on the client. The cookie data is encoded with the Base64UrlTextEncoder. The cookie is encrypted and chunked, so the single cookie size limit does not apply. See CookieTempDataProvider for more information.+
The cookie data is not compressed. Using compression with encryption can lead to security problems such as the CRIME and BREACH attacks.+
Query strings are useful for capturing state in a persistent manner, allowing links with embedded state to be created and shared through email or social networks. However, no assumption can be made about the user making the request, since URLs with query strings can easily be shared. Care must also be taken to avoid Cross-Site Request Forgery (CSRF) attacks. An attacker could trick a user into visiting a malicious site while authenticated. CSRF are a major form of vulnerability that can be used to steal user data from your app, or take malicious actions on the behalf of the user. Any preserved application or session state needs to protect against CSRF attacks. See Preventing Cross-Site Request Forgery (XSRF/CSRF) Attacks in ASP.NET Core+
Cookies are often used for personalization, where content is customized for a known user. In most cases, identification is the issue rather than authentication. Thus, you can typically secure a cookie that is used for identification by storing the user name, account name, or a unique user ID (such as a GUID) in the cookie and then use the cookie to access the user personalization infrastructure of a site.+
+
Add any of the IDistributedCache memory caches. The
Call AddSession, which requires NuGet package "Microsoft.AspNetCore.Session".
Call UseSession.
+
The following code shows how to set up the in-memory session provider:+
Copy
C#
You can reference Session from
Note: Accessing
Attempting to create a new
If applications wish to enforce this pattern, they could wrap the DistributedSessionStore and DistributedSession implementations with versions that throw if the
Session defaults can be overridden by using
Copy
C#
The
Note:
The following example shows setting and getting an int and a string:+
Copy
C#
If you add the following extension methods, you can set and get serializable objects to Session:+
Copy
C#
The following sample shows how to set and get a serializable object:+
Copy
C#
In the sample below, Middleware adds
Copy
C#
Later in the pipeline, another middleware could access it:+
Copy
C#
Note: Since keys into
+
Define a service containing the data (for example, a class named
+
Copy
C#
Add the service class to
Consume the data service class in each controller:
+
Copy
C#
Commonly caused by not configuring at least one
+
By Rick Anderson and Steve Smith+
HTTP is a stateless protocol; the Web server treats each HTTP request as an independent request. The server retains no knowledge of variable values that were used in previous requests. This article discusses various approaches to preserving application and user (session) state between requests. +
Application state, unlike session state, applies to all users and sessions.+
Session state
Session state is a feature in ASP.NET Core you can enable that allows you to save and store user data while the user browses your web app. Session data is stored in dictionary on the server and persists data across requests from a browser. A session ID is stored on the client in a cookie. The session ID cookie is sent to server with each request, and the server uses the session ID to fetch the session data. The session ID cookie is per browser, you cannot share session across browsers. Session cookies have no specified timeout, they are deleted when the browser session ends. If a cookie is received for an expired session, then a new session is created using the same Session cookie.+Session is retained by the server for a limited time after the last request. The default session timeout is 20 minutes, but you can configure session time out. The session data is backed by a cache. Session is ideal for storing user state that is specific to a particular session but which doesn’t need to be persisted permanently. Data is deleted from the backing store either when you call
Session.Clearor when the session expires in the data store. The server does not know when the browser is closed or the Session cookie is deleted.+
Warning
Sensitive data should never be stored in session. You can’t guarantee the client will close the browser and clear their session cookie (and some browsers keep them alive across windows). Consequently, you can’t assume that a session is restricted to a single user, the next user may continue with the same session.+
The in-memory session provider stores session data on the server, which can impact scale out. If you run your web app on a server farm, you’ll need to enable sticky sessions to tie each session to a specific server. Windows Azure Web Sites defaults to sticky sessions (Application Request Routing or ARR). Sticky session can impact scalability and complicate updating your web app. The Redis and SQL Server distributed caches don't require sticky sessions and are the preferred approach to multi-server caching. See Working with a Distributed Cache for more information.+
See Configuring Session below for more details.+
TempData
ASP.NET Core MVC exposes the TempData property on a Controller.TempDatacan be used for storing transient data that only needs to be available for a single request after the current request.
TempDatais frequently useful for redirection, when data is needed for more than a single request.
TempDatais built on top of Session State.+
Cookie-based TempData provider (requires ASP.NET Core 1.1.0 and higher)
To enable the Cookie-based TempData provider, register theCookieTempDataProviderservice in
ConfigureServices:+
Copy
C#
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); // Add CookieTempDataProvider after AddMvc and include ViewFeatures. // using Microsoft.AspNetCore.Mvc.ViewFeatures; services.AddSingleton<ITempDataProvider, CookieTempDataProvider>(); }
The cookie-based TempData provider does not use Session; data is stored in a cookie on the client. The cookie data is encoded with the Base64UrlTextEncoder. The cookie is encrypted and chunked, so the single cookie size limit does not apply. See CookieTempDataProvider for more information.+
The cookie data is not compressed. Using compression with encryption can lead to security problems such as the CRIME and BREACH attacks.+
Query strings
State from one request can be provided to another request by adding values to the new request's query string. Query strings should never be used with sensitive data. It is also best used with small amounts of data.+Query strings are useful for capturing state in a persistent manner, allowing links with embedded state to be created and shared through email or social networks. However, no assumption can be made about the user making the request, since URLs with query strings can easily be shared. Care must also be taken to avoid Cross-Site Request Forgery (CSRF) attacks. An attacker could trick a user into visiting a malicious site while authenticated. CSRF are a major form of vulnerability that can be used to steal user data from your app, or take malicious actions on the behalf of the user. Any preserved application or session state needs to protect against CSRF attacks. See Preventing Cross-Site Request Forgery (XSRF/CSRF) Attacks in ASP.NET Core+
Post data and hidden fields
Data can be saved in hidden form fields and posted back on the next request. This is common in multi-page forms. It’s insecure in that the client can tamper with the data so the server must always revalidate it.+Cookies
Data can be stored in cookies. Cookies are sent with every request, so the size should be kept to a minimum. Ideally, only an identifier should be used, with the actual data stored somewhere on the server. Cookies are subject to tampering and therefore need to be validated on the server. Cookies are limited by most browsers to 4096 bytes and you have only a limited number of cookies per domain. Although the durability of the cookie on a client is subject to user intervention and expiration, cookies are generally the most durable form of data persistence on the client.+Cookies are often used for personalization, where content is customized for a known user. In most cases, identification is the issue rather than authentication. Thus, you can typically secure a cookie that is used for identification by storing the user name, account name, or a unique user ID (such as a GUID) in the cookie and then use the cookie to access the user personalization infrastructure of a site.+
HttpContext.Items
TheItemscollection is the good location to store data that is only needed while processing a given request. Its contents are discarded after each request. It is best used as a means of communicating between components or middleware that operate at different points in time during a request and have no direct way to pass parameters. See Working with HttpContext.Items, below.+
Cache
Caching provides a means of efficiently storing and retrieving data. It provides rules for expiring cached items based on time and other considerations. Learn more about Caching.++
Configuring Session
TheMicrosoft.AspNetCore.Sessionpackage provides middleware for managing session state. Enabling the session middleware requires the following in
Startup:+
Add any of the IDistributedCache memory caches. The
IDistributedCacheimplementation is used as a backing store for session.
Call AddSession, which requires NuGet package "Microsoft.AspNetCore.Session".
Call UseSession.
+
The following code shows how to set up the in-memory session provider:+
Copy
C#
using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using System; public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddMvc(); // Adds a default in-memory implementation of IDistributedCache. services.AddDistributedMemoryCache(); services.AddSession(options => { // Set a short timeout for easy testing. options.IdleTimeout = TimeSpan.FromSeconds(10); options.CookieHttpOnly = true; }); } public void Configure(IApplicationBuilder app) { app.UseSession(); app.UseMvcWithDefaultRoute(); } }
You can reference Session from
HttpContextonce it is installed and configured.+
Note: Accessing
Sessionbefore
UseSessionhas been called throws
InvalidOperationException: Session has not been configured for this application or request.+
Attempting to create a new
Session(that is, no session cookie has been created) after you have already begun writing to the
Responsestream throws
InvalidOperationException: The session cannot be established after the response has started. The exception can be found in the web server log, it will not be displayed in the browser.+
Loading Session asynchronously
The default session provider in ASP.NET Core will only load the session record from the underlying IDistributedCache store asynchronously if the ISession.LoadAsync method is explicitly called before calling theTryGetValue,
Setor
Removemethods. Failure to call
LoadAsyncfirst will result in the underlying session record being loaded synchronously, which could potentially impact the ability of the app to scale.+
If applications wish to enforce this pattern, they could wrap the DistributedSessionStore and DistributedSession implementations with versions that throw if the
LoadAsyncmethod has not been called before calling
TryGetValue,
Setor
Remove, and register the wrapped versions in the services container.+
Implementation Details
Session uses a cookie to track and identify requests from the same browser. By default this cookie is named ".AspNet.Session" and uses a path of "/". The cookie default does not specify a domain. The cookie default is not made available to client-side script on the page (becauseCookieHttpOnlydefaults to
true).+
Session defaults can be overridden by using
SessionOptions:+
Copy
C#
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); // Adds a default in-memory implementation of IDistributedCache. services.AddDistributedMemoryCache(); services.AddSession(options => { options.CookieName = ".AdventureWorks.Session"; options.IdleTimeout = TimeSpan.FromSeconds(10); }); }
The
IdleTimeoutis used by the server to determine how long a session can be idle before its contents are abandoned.
IdleTimeoutis independent of the cookie expiration. Each request that passes through the Session middleware (read from or written to) will reset the timeout.+
Note:
Sessionis non-locking, so if two requests both attempt to modify the contents of session, the last one will win.
Sessionis implemented as a coherent session, which means that all of the contents are stored together. This means that if two requests are modifying different parts of the session (different keys), they may still impact each other.+
Setting and getting Session values
Session is accessed through theSessionproperty on
HttpContext.
Sessionis an ISession implementation.+
The following example shows setting and getting an int and a string:+
Copy
C#
public class HomeController : Controller { const string SessionKeyName = "_Name"; const string SessionKeyYearsMember = "_YearsMember"; const string SessionKeyDate = "_Date"; public IActionResult Index() { // Requires using Microsoft.AspNetCore.Http; HttpContext.Session.SetString(SessionKeyName, "Rick"); HttpContext.Session.SetInt32(SessionKeyYearsMember, 3); return RedirectToAction("SessionNameYears"); } public IActionResult SessionNameYears() { var name = HttpContext.Session.GetString(SessionKeyName); var yearsMember = HttpContext.Session.GetInt32(SessionKeyYearsMember); return Content($"Name: \"{name}\", Membership years: \"{yearsMember}\""); }
If you add the following extension methods, you can set and get serializable objects to Session:+
Copy
C#
using Microsoft.AspNetCore.Http; using Newtonsoft.Json; public static class SessionExtensions { public static void Set<T>(this ISession session, string key, T value) { session.SetString(key, JsonConvert.SerializeObject(value)); } public static T Get<T>(this ISession session,string key) { var value = session.GetString(key); return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value); } }
The following sample shows how to set and get a serializable object:+
Copy
C#
public IActionResult SetDate() { // Requires you add the Set extension method mentioned in the article. HttpContext.Session.Set<DateTime>(SessionKeyDate, DateTime.Now); return RedirectToAction("GetDate"); } public IActionResult GetDate() { // Requires you add the Get extension method mentioned in the article. var date = HttpContext.Session.Get<DateTime>(SessionKeyDate); var sessionTime = date.TimeOfDay.ToString(); var currentTime = DateTime.Now.TimeOfDay.ToString(); return Content($"Current time: {currentTime} - " + $"session time: {sessionTime}"); }
Working with HttpContext.Items
TheHttpContextabstraction provides support for a simple dictionary collection of type
IDictionary<object, object>, called
Items. This collection is available from the start of an HttpRequest and is discarded at the end of each request. You can access it by assigning a value to a keyed entry, or by requesting the value for a given key.+
In the sample below, Middleware adds
isVerifiedto the
Itemscollection:+
Copy
C#
app.Use(async (context, next) => { // perform some verification context.Items["isVerified"] = true; await next.Invoke(); });
Later in the pipeline, another middleware could access it:+
Copy
C#
app.Run(async (context) => { await context.Response.WriteAsync("Verified request? " + context.Items["isVerified"]); });
Note: Since keys into
Itemsare simple strings, if you are developing middleware that needs to work across many applications, you may wish to prefix your keys with a unique identifier to avoid key collisions (for example, "MyComponent.isVerified" instead of "isVerified").+
+
Application state data
Use Dependency Injection to make data available to all users.+Define a service containing the data (for example, a class named
MyAppData).
+
Copy
C#
public class MyAppData { // Declare properties/methods/etc. }
Add the service class to
ConfigureServices(for example
services.AddSingleton<MyAppData>();.
Consume the data service class in each controller:
+
Copy
C#
public class MyController : Controller { public MyController(MyAppData myService) { // Do something with the service (read some data from it, // store it in a private field/property, etc. } } }
Common errors when working with session
"Unable to resolve service for type 'Microsoft.Extensions.Caching.Distributed.IDistributedCache' while attempting to activate 'Microsoft.AspNetCore.Session.DistributedSessionStore'."Commonly caused by not configuring at least one
IDistributedCacheimplementation. See Working with a Distributed Cache and In memory caching for more information
+
Additional Resources
Sample code used in this document相关文章推荐
- [本周]随手记下 Asp.net中Application Session Cookie ViewState Cache Hidden
- [本周]随手记下 Asp.net中Application Session Cookie ViewState Cache Hidden
- Asp.net中Application Session Cookie ViewState Cache Hidden
- ASP.NET Application,Session,Cookie和ViewState等对象用法和区别
- MVC architecture in ASP.Net using C# and Microsoft Data Access Application block
- ASP.NET Application,Session,Cookie和ViewState等对象用法和区别 (转)
- Session state cannot be used in ASP.NET with Windows SharePoint Services
- ASP.NET Application,Session,Cookie和ViewState等对象用法和区别
- Asp.net中Application Session Cookie ViewState Cache Hidden
- ASP.NET的Application、Session、Cookie、ViewState和Cache等变量的区别是什么?
- Asp.net中Application Session Cookie ViewState Cache Hidden 区别
- cache:缓存在asp.net中如何管理?服务器端缓存?Session, Application, Cache objectscache ,客户端缓存?Cookies,ViewState
- ASP.NET Application,Session,Cookie和ViewState等对象用法和区别 (转)
- Asp.net中Application Session Cookie ViewState Cache Hidden
- Asp.net中Application Session Cookie ViewState Cache Hidden
- Troubleshooting Expired ASP.NET Session State and Your Options
- Asp.net中Application Session Cookie ViewState Cache Hidden
- ASP.NET Application,Session,Cookie和ViewState等对象用法和区别
- How to Share Session/Application State Across Different ASP.NET Web Applications
- Asp.net中Application Session Cookie ViewState Cache