📄 sqlstateclientmanager.cs
字号:
//------------------------------------------------------------------------------
// <copyright file="SqlSessionStateStore.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
/*
* SqlSessionStateStore.cs
*
* Copyright (c) 1998-2000, Microsoft Corporation
*
*/
namespace Microsoft.Samples {
using System;
using System.Configuration;
using System.Collections;
using System.Threading;
using System.IO;
using System.Web;
using System.Web.Caching;
using System.Web.Util;
using System.Data;
using System.Data.SqlClient;
using System.Data.Common;
using System.Text;
using System.Security.Principal;
using System.Xml;
using System.Collections.Specialized;
using System.Configuration.Provider;
using System.Globalization;
using System.Web.Management;
using System.Web.Hosting;
using System.Web.Configuration;
using System.Web.SessionState;
/*
* Provides session state via SQL Server
*/
public class SqlSessionStateStore : SessionStateStoreProviderBase {
internal enum SupportFlags : uint {
None = 0x00000000,
GetLockAge = 0x00000001,
Uninitialized = 0xFFFFFFFF
}
#pragma warning disable 0649
// static ReadWriteSpinLock s_lock;
#pragma warning restore 0649
static int s_commandTimeout;
static bool s_oneTimeInited;
static bool s_usePartition = false;
static EventHandler s_onAppDomainUnload;
// We keep these info because we don't want to hold on to the config object.
static string s_configPartitionResolverType = null;
static string s_configSqlConnectionFileName;
static int s_configSqlConnectionLineNumber;
static bool s_configAllowCustomSqlDatabase;
static string s_sqlConnectionString;
static SqlPartitionInfo s_singlePartitionInfo;
// Per request info
HttpContext _rqContext;
int _rqOrigStreamLen;
//IPartitionResolver _partitionResolver = null;
SqlPartitionInfo _partitionInfo;
const int ITEM_SHORT_LENGTH = 7000;
const int SQL_ERROR_PRIMARY_KEY_VIOLATION = 2627;
const int SQL_LOGIN_FAILED = 18456;
const int SQL_LOGIN_FAILED_2 = 18452;
const int SQL_LOGIN_FAILED_3 = 18450;
const int APP_SUFFIX_LENGTH = 8;
static int ID_LENGTH = SessionIDManager.SessionIDMaxLength + APP_SUFFIX_LENGTH;
internal const int SQL_COMMAND_TIMEOUT_DEFAULT = 30; // in sec
public SqlSessionStateStore() {
}
/*
internal override void Initialize(string name, NameValueCollection config, IPartitionResolver partitionResolver) {
_partitionResolver = partitionResolver;
Initialize(name, config);
}
*/
#if DBG
SessionStateModule _module;
internal void SetModule(SessionStateModule module) {
_module = module;
}
#endif
public override void Initialize(string name, NameValueCollection config)
{
if (String.IsNullOrEmpty(name))
name = "SQL Server Session State Provider";
base.Initialize(name, config);
if (!s_oneTimeInited) {
// s_lock.AcquireWriterLock();
try {
if (!s_oneTimeInited) {
OneTimeInit();
}
}
finally {
// s_lock.ReleaseWriterLock();
}
}
_partitionInfo = s_singlePartitionInfo;
}
void OneTimeInit() {
SessionStateSection config = (SessionStateSection)WebConfigurationManager.GetSection("system.web/sessionState");
s_configSqlConnectionFileName = config.ElementInformation.Properties["sqlConnectionString"].Source;
s_configSqlConnectionLineNumber = config.ElementInformation.Properties["sqlConnectionString"].LineNumber;
s_configAllowCustomSqlDatabase = config.AllowCustomSqlDatabase;
s_sqlConnectionString = config.SqlConnectionString;
if (String.IsNullOrEmpty(s_sqlConnectionString)) throw new Exception("No connection string specified");
s_singlePartitionInfo = CreatePartitionInfo(s_sqlConnectionString);
s_commandTimeout = (int)config.SqlCommandTimeout.TotalSeconds;
// We only need to do this in one instance
s_onAppDomainUnload = new EventHandler(OnAppDomainUnload);
Thread.GetDomain().DomainUnload += s_onAppDomainUnload;
// Last thing to set.
s_oneTimeInited = true;
}
void OnAppDomainUnload(Object unusedObject, EventArgs unusedEventArgs) {
//Debug.Trace("SqlSessionStateStore", "OnAppDomainUnload called");
Thread.GetDomain().DomainUnload -= s_onAppDomainUnload;
}
internal SqlPartitionInfo CreatePartitionInfo(string sqlConnectionString) {
/*
* Parse the connection string for errors. We want to ensure
* that the user's connection string doesn't contain an
* Initial Catalog entry, so we must first create a dummy connection.
*/
SqlConnection dummyConnection;
string attachDBFilename = null;
try {
dummyConnection = new SqlConnection(sqlConnectionString);
}
catch (Exception e) {
throw new Exception(
SR.GetString(SR.Error_parsing_session_sqlConnectionString, e.Message),
e);
}
// Search for both Database and AttachDbFileName. Don't append our
// database name if either of them exists.
string database = dummyConnection.Database;
SqlConnectionStringBuilder scsb = new SqlConnectionStringBuilder(sqlConnectionString);
if (String.IsNullOrEmpty(database)) {
database = scsb.AttachDBFilename;
attachDBFilename = database;
}
if (!String.IsNullOrEmpty(database)) {
if (!s_configAllowCustomSqlDatabase) {
throw new Exception(SR.GetString(SR.No_database_allowed_in_sqlConnectionString));
}
if (attachDBFilename != null) {
// HttpRuntime.CheckFilePermission(attachDBFilename, true);
}
}
else {
scsb.Add("Initial Catalog", "ASPState");
}
return new SqlPartitionInfo(new ResourcePool(new TimeSpan(0, 0, 5), int.MaxValue),
scsb.IntegratedSecurity,
scsb.ConnectionString);
}
public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback) {
return false;
}
public override void Dispose() {
}
public override void InitializeRequest(HttpContext context) {
////Debug.Assert(context != null, "context != null");
_rqContext = context;
_rqOrigStreamLen = 0;
/* if (s_usePartition) {
// For multiple partition case, the connection info can change from request to request
_partitionInfo = null;
}
*
*
*/
}
public override void EndRequest(HttpContext context) {
////Debug.Assert(context != null, "context != null");
_rqContext = null;
}
public bool KnowForSureNotUsingIntegratedSecurity {
get {
if (_partitionInfo == null) {
////Debug.Assert(s_usePartition, "_partitionInfo can be null only if we're using paritioning and we haven't called GetConnection yet.");
// If we're using partitioning, we need the session id to figure out the connection
// string. Without it, we can't know for sure.
return false;
}
else {
////Debug.Assert(_partitionInfo != null);
return !_partitionInfo.UseIntegratedSecurity;
}
}
}
//
// Regarding resource pool, we will turn it on if in <identity>:
// - User is not using integrated security
// - impersonation = "false"
// - impersonation = "true" and userName/password is NON-null
// - impersonation = "true" and IIS is using Anonymous
//
// Otherwise, the impersonated account will be dynamic and we have to turn
// resource pooling off.
//
// Note:
// In case 2. above, the user can specify different usernames in different
// web.config in different subdirs in the app. In this case, we will just
// cache the connections in the resource pool based on the identity of the
// connection. So in this specific scenario it is possible to have the
// resource pool filled with mixed identities.
//
bool CanUsePooling() {
bool ret = false;
if (KnowForSureNotUsingIntegratedSecurity) {
//Debug.Trace("SessionStatePooling", "CanUsePooling: not using integrated security");
ret = true;
}
else if (_rqContext == null) {
// One way this can happen is we hit an error on page compilation,
// and SessionStateModule.OnEndRequest is called
//Debug.Trace("SessionStatePooling", "CanUsePooling: no context");
ret = false;
}
// else if (!_rqContext.IsClientImpersonationConfigured) {
//Debug.Trace("SessionStatePooling", "CanUsePooling: mode is None or Application");
//ret = true;
// }
// else if (HttpRuntime.IsOnUNCShareInternal) {
//Debug.Trace("SessionStatePooling", "CanUsePooling: mode is UNC");
// ret = false;
// }
else {
/* string logon = _rqContext.WorkerRequest.GetServerVariable("LOGON_USER");
//Debug.Trace("SessionStatePooling", "LOGON_USER = '" + logon + "'; identity = '" + _rqContext.User.Identity.Name + "'; IsUNC = " + HttpRuntime.IsOnUNCShareInternal);
if (String.IsNullOrEmpty(logon)) {
ret = true;
}
else {
ret = false;
}
*/
}
//Debug.Trace("SessionStatePooling", "CanUsePooling returns " + ret);
return ret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -