Session ending before web.config timeout - asp.net

I have an ASP.NET MVC application for which I've configured sessions in the web.config as follows:
<!--
If you are deploying to a cloud environment that has multiple web server instances,
you should change session state mode from "InProc" to "Custom". In addition,
change the connection string named "DefaultConnection" to connect to an instance
of SQL Server (including SQL Azure and SQL Compact) instead of to SQL Server Express.
-->
<sessionState customProvider="DefaultSessionProvider" mode="InProc" timeout="65">
<providers>
<add name="DefaultSessionProvider"
type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
connectionStringName="DefaultConnection" />
</providers>
</sessionState>
FYI, our production environment has four app servers which is I assume why the DefaultSessionProvider was set (by someone else).
I'm using a SessionHelper class to store information in the session:
public class SessionHelper : ISessionHelper
{
private readonly HttpContextBase context;
public SessionHelper(HttpContextBase context)
{
this.context = context;
}
public int? GetUserId()
{
return getSessionValue<int?>(USER_ID_KEY);
}
private T getSessionValue<T>(string key)
{
var value = context.Session[key];
if (value == null)
{
return default(T);
}
return (T)value;
}
}
I'm using Ninject to inject HttpContextBase like so:
kernel.Bind<HttpContextBase>().ToMethod(ctx => new HttpContextWrapper(HttpContext.Current)).InTransientScope();
What I'm seeing is that before the timeout of 65 mins which I have set in the web.config, the session variables are null. I also noticed Session_End() in my Global.asax.cs being called.
I've done some research and the information I found regarding sessions ending prematurely seems to be focused on things that would affect all users like files being changed in the bin directory causing the app pool to restart. Things like that. I believe my issue is on a session-by-session basis.
Why is my session ending before I want it to? Thanks in advance.

Related

ProfileCommon.GetProfile(string)' hides inherited member '.UserProfile.GetProfile(string)'. Use the new keyword if hiding was intended

I am using aspnet membership profile and Inherited the profileBase class to a class name UserProfile, where I have defined the method GetProfile. Everything working fine But while build getting the above warning.
Please help how to remove the warning.
Below the sample codes.
public static UserProfile GetProfile(string userName)
{
return (UserProfile)Create(userName);
}
public static UserProfile GetProfile(string username, bool authenticated)
{
return (UserProfile)Create(username, authenticated);
}
public static UserProfile Current()
{
return ((UserProfile)(HttpContext.Current.Profile));
}
<!-- Profile configuration -->
<profile enabled="true" defaultProvider="EFProfileProvider" inherits="Jan.DB.Provider.UserProfile" automaticSaveEnabled="true">
<providers>
<clear/>
<add name="EFProfileProvider" type="Jan.DB.Provider.EFProfileProvider" connectionStringName="JanEntities" applicationName=""/>
</providers>
</profile>
While migrating from simple membership to Identity we had made some mistake. Although we have removed all the membership related codes. One thing we have done is how profile is handled. I mean in idenity customization we have used the old UserProfile.cs of membership with some customization. But as we are using
in web.config so at runtime Asp.net memebrship automatically creates the ProfileCommon.cs and for that we are getting that warning.
so can avoid that warning by cleaning of the customization and moved to how identity handles the profile information.

Custom Role Provider not called. What am I doing wrong?

So I'm trying to create a Hello World custom Role Provider-solution in ASP.NET MVC 4.
Basically I've set authentication mode="Windows" in web.config along with defining a role provider like this:
<roleManager enabled="true" defaultProvider="MyRoleProvider">
<providers>
<clear />
<add name="MyRoleProvider" type="MyProject.Code.MyRoleProvider" />
</providers>
</roleManager>
Then I've decorated the About controller method like this:
[Authorize(Roles = "SomeRole")]
public ActionResult About()
{ /* ... */ }
The custom RoleProvider-class looks like this:
namespace MyProject.Code {
public class MyRoleProvider : RoleProvider
{
public override bool IsUserInRole(string username, string roleName)
{
if (roleName == "SomeRole" && username = "Administrator") return true;
return false;
}
public override string[] GetRolesForUser(string username)
{
return new string[] { "SomeRole" };
}
/* a bunch of other overridden methods simply throwing not implementedException */
}
}
Now the thing is I've put a breakpoint on every single executable line of code in MyRoleProvder but none are hit. I have tested that breakpoints elsewhere are hit so the debugger is not the problem. Why isn't my code in the role provided executed? I was expecting IsUserInRole and/or GetRolesForUser to be executed when I navigate to the About-page. Am I wrong? Have I configured something wrong?
Full web.config for reference
edit: The user is redirected to the login page when the about page is clicked. I now realize this is due to the user actually is not authenticated yet. Authorization naturally happens after authentication. Is IISExpress not providing Windows identity?
As this is the first result in a google search i want to give a solution, maybe for others:
To use the windows identity in IIEExpress you have to activate it in your applicationhost.config , which is located in
[SolutionDir].vs\config\applicationhost.config
there you can find the xml tag
<configuration>
<system.webServer>
<security>
<authentication>
<windowsAuthentication enabled="false">
change enabled="false" to enabled="true"
and you can use windows authenticatuion in IISExpress
I think your type declaration is incomplete, you should include both the full name and the assembly name.
type="MyProject.Code.MyRoleProvider, MyProject"
You might also need to set Version, Culture and PublicKeyToken if your assemblies are place in the GAC
Hope this helps

Mysql syntax error while creating Database for Entity Framework

I'm playing around with asp.net for the first time. I want to use it with a MySQL database because this is what is offered by my hosting service and I don't want to upgrade/change services. I'm using visual web developer 2010 express. I created an MVC 4 project from the default template. The template created the ASP.NET Simple Membership objects which is what I'm trying to get working. The project builds and runs correctly when using the default database connection string. When I change the web.config file to point to MySQL I get the following error when I attempt to navigate to any of the pages in the account folder.
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'IDENTITY,
RoleName nvarc' at line 2
When I open the MySQL work bench and connect to the local server I notice that the database has been created. If I drop the DB and run the app again it gets recreated. I'm note sure if it was created correctly or if the entire database was created but there is something there.
Obviously there is an issue with the SQL syntax that is created by the Entity Framework. Do I need to add something to the web.config file to tell it what syntax it should use when creating the queries?
I've been searching for an answer to this for the past two days. any help pointing in the right direction would be appreciated.
I'm using mysql server version 5.5.27. and connector 6.5.4.0
here is the mysql part of my web.config file:
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient"/>
<add name="MySQL Data Provider"
invariant="MySql.Data.MySqlClient"
description=".Net Framework Data Provider for MySQL"
type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=aspnet-MyWebPage-20120817115958;Integrated Security=SSPI" providerName="System.Data.SqlClient" />
<add name="myDatabaseConnection" connectionString="server=localhost;Port=3306;uid=root;pwd=****;database=myDatabase;" providerName="MySql.Data.MySqlClient" />
</connectionStrings>
Edit adding code
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer<UsersContext>(null);
try
{
using (var context = new UsersContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
WebSecurity.InitializeDatabaseConnection("LocalMySqlServer", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}
catch (Exception ex)
{
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
}
}
public class UsersContext : DbContext
{
public UsersContext()
: base("LocalMySqlServer")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
}
Try to modify the source of the SMP and remove the syntax specific to ms sql server.
The role provider is still defaulting to the standard ASP one which is expecting a SQLServer DB on the end of the connection, "Identity" is SQLServerese for "autoinc".
You can set the default providers in the web.config like this:-
<configuration>
<system.web>
<profile defaultProvider="MySQLProfileProvider"></profile>
<roleManager defaultProvider="MySQLRoleProvider"></roleManager>
</system.web>
</configuration>

Substituting values into web.config at runtime

We have an application that runs in three environments: development, QA, and production. The application accesses an SQL server and several web services. The web.config file has the connection string for the SQL server and the IP addresses of the web services. We would like to be able to have one web.config file that works in all three environments, but somehow picks up the varying data for each environment. Does anyone know of a way to do this?
Look at Web.config Transformation.
We use the exact same config options as you, and we have created 3 connection strings in our web.config like this:
<connectionStrings>
<add name="Dev" connectionString="Server=localhost;Database=WebDev;User=devo;Pwd=xxxxx;" providerName="System.Data.SqlClient"/>
<add name="Stage" connectionString="Server=localhost;Database=WebStage;User=stago;Pwd=xxxxx;" providerName="System.Data.SqlClient"/>
<add name="Live" connectionString="Server=localhost;Database=WebLive;User=livo;Pwd=xxxxx;" providerName="System.Data.SqlClient"/>
</connectionStrings>
Then we have a static method that bases itself on the url to determine which conn str to use:
public static string ConnStr
{
get
{
if (Config.WebRoot.StartsWith("http://www.")) { return ConfigurationManager.ConnectionStrings["Live"].ToString(); }
else if (Config.WebRoot.StartsWith("http://stage.")) { return ConfigurationManager.ConnectionStrings["Stage"].ToString(); }
else if (Config.WebRoot.StartsWith("http://localhost")) { return ConfigurationManager.ConnectionStrings["Dev"].ToString(); }
else { return null; }
}
}
You may have to adjust the method to work for you.

ASP.NET aspx page code runs impersonated though impersonation is disabled

I have a blank test app created in VS 2005 as ASP.NET application. MSDN says that
By default, ASP.NET does not use impersonation, and your code runs using the ASP.NET application's process identity.
And I have the following web.config
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<!--
Set compilation debug="true" to insert debugging
symbols into the compiled page. Because this
affects performance, set this value to true only
during development.
-->
<compilation debug="true" defaultLanguage="c#" />
<!--
The <authentication> section enables configuration
of the security authentication mode used by
ASP.NET to identify an incoming user.
-->
<authentication mode="Windows"/>
<identity impersonate="false"/>
<!--
The <customErrors> section enables configuration
of what to do if/when an unhandled error occurs
during the execution of a request. Specifically,
it enables developers to configure html error pages
to be displayed in place of a error stack trace.
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
-->
</system.web>
</configuration>
So it seem impersonation is disabled just like the article is suggesting.
My aspx is blank default and the codebehind is
namespace TestWebapp
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine(String.Format("Before1: Current Princupal = {0}", Thread.CurrentPrincipal.Identity.Name));
WindowsImpersonationContext ctx = WindowsIdentity.Impersonate(IntPtr.Zero);
try
{
int a = 0;
System.Diagnostics.Debug.WriteLine(String.Format("After: Current Princupal = {0}", Thread.CurrentPrincipal.Identity.Name));
} finally
{
ctx.Undo();
}
}
}
}
When I reload the page I get the following debug output:
[5288] Before1: Current Princupal =
DOMAIN\User
[5288] After: Current Princupal =
DOMAIN\User
Output is the same with
<identity impersonate="false"/>
The web site uses Default Application Pool and the pool is set up to use NETWORK SERVICE account for its worker processes.
I'm sure the application uses the web.config it should use and the w3p.exe worker process is running under NETWORK SERVICE.
What can be wrong in this case?
Thanks!
#Edit: Rob, thanks for the tip!
The $user shortcut shows me that everything is happening as I expect: with impersonation on I have the process running user NT AUTHORITY\NETWORK SERVICE and the thread has DOMAIN\User before WindowsIdentity.Impersonate(IntPtr.Zero) and "No Token. Thread not impersonating." after.
But Thread.CurrentPrincipal.Identity.Name and HttpContext.Current.User.Identity.Name still give me DOMAIN\User in both places.
#Edit: I've found out that to get Thread.CurrentPrincipal and HttpContext.Current.User changed I have to manually do it:
Thread.CurrentPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
HttpContext.Current.User = Thread.CurrentPrincipal;
I'm not sure what's the point here, but anyway. I now have a problem with sharepoint shared services manage user profile permission but that's another question.
I think I understand your problem here.
Things to know before moving further,
There are different security context while an application is running. Like System.Security.Principal.WindowsIdentity.GetCurrent().Name, and the one you mentioned above, i.e. System.Threading.Thread.CurrentPrincipal.Identity.Name
In a web application, System.Threading.Thread.CurrentPrincipal.Identity is always provided by HttpContext.Current.User.Identity.
Coming to your point. If you want to modify System.Threading.Thread.CurrentPrincipal.Identity, then modify HttpContext.Current.User.Identity which initially provided by your authentication mechanism.
Seems odd, A few things to try:
While in on a breakpoint in Debug type $user in a watch window, that will show you the process and thread identities.
Your use of impersonate is incorrect, try this code:
// Declare the logon types as constants
const long LOGON32_LOGON_INTERACTIVE = 2;
const long LOGON32_LOGON_NETWORK = 3;
// Declare the logon providers as constants
const long LOGON32_PROVIDER_DEFAULT = 0;
const long LOGON32_PROVIDER_WINNT50 = 3;
const long LOGON32_PROVIDER_WINNT40 = 2;
const long LOGON32_PROVIDER_WINNT35 = 1;
[DllImport("advapi32.dll", EntryPoint = "LogonUser")]
private static extern bool LogonUser(
string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
public static WindowsImpersonationContext ImpersonateCurrentUserBegin(System.Net.NetworkCredential credential)
{
WindowsImpersonationContext impersonationContext = null;
if (credential == null || credential.UserName.Length == 0 || credential.Password.Length == 0 || credential.Domain.Length == 0)
{
throw new Exception("Incomplete user credentials specified");
}
impersonationContext = Security.Impersonate(credential);
if (impersonationContext == null)
{
return null;
}
else
{
return impersonationContext;
}
}
public static void ImpersonateCurrentUserEnd(WindowsImpersonationContext impersonationContext)
{
if (impersonationContext != null)
{
impersonationContext.Undo();
}
}
What does HttpContext.User.Identity.Name give you?
Assume you've checked the security tab within IIS that it allows anonymous access?
Are you within an active directory that has some strange local policy?

Resources