I have been faced with this problem for months and I have read almost all I can about this and implemented most solutions but still nothing has changed. I don't know where I am making my mistake.
I am using a custom SessionManager class to get/set values into Session easily in my ASP.net CMS websites' admin panels. When the user logins I store user data to the Session then read in Admin.master page to check if the user is logged in. On different servers and also on localhost, the SessionManager.CurrentUser value is null at random times, sometimes 2 minutes sometimes 20 minutes after login, whether the page is idle or not. All my websites have the same problem.
My SessionManager.cs is
public class SessionManager
{
public SessionManager() { }
public static User CurrentUser
{
get { return (User)HttpContext.Current.Session["crntUsr"]; }
set { HttpContext.Current.Session["crntUsr"] = value; }
}
public static string CurrentAdminLanguage
{
get
{
if (HttpContext.Current.Session["crntLang"] == null) HttpContext.Current.Session["crntLang"] = SiteSettings.DefaultLanguage;
return HttpContext.Current.Session["crntLang"].ToString();
}
set
{
HttpContext.Current.Session["crntLang"] = value;
}
}
}
Note: User class is [Serializable]
In Admin.master Page_Load
if (SessionManager.CurrentUser == null) Response.Redirect("../login");
In web.config
<system.web>
<sessionState mode="InProc" customProvider="DefaultSessionProvider" cookieless="UseCookies" regenerateExpiredSessionId="true" timeout="60"/>
<machineKey validationKey="CC0...F80" decryptionKey="8BF...1B5" validation="SHA1" decryption="AES"/>
<authentication mode="Forms">
<forms loginUrl="~/login" timeout="60" slidingExpiration="true" cookieless="UseCookies" />
</authentication>
<system.webServer>
<modules>
<remove name="Session"/>
<add name="Session" type="System.Web.SessionState.SessionStateModule"/>
</modules>
I really have no more ideas to solve this issue. Please help :(
Have you checked your application pool recycling timeout? That's a common issue for session "disappearing" prior than expected. Check in IIS
If you have problems, you could set up SQL Server for handling the session, which will persist it if the AppPool is recycled, or the server is rebooted.
For more information: http://support.microsoft.com/kb/317604
Here is a sample web.config code. I don't like the regenerateExpiredSessionId in there and also it is a good practice to have your session timeout to be less than your forms timeout. How ever my advice is to carefully examine your session manager code so you can be sure that you don't reset it somehow. I can think of two thing you could do:
1. Make a test page to check when the session is empty or not and to see if you can at all set a session variable. Try to do a button click (or a ajax request) and set a session variable to keep the session alive every 1 minute or so to see if it expires again even if you keep it alive. If you don't use the Session it will expire. 2. Do some kind of logging. Every time you set a session variable do a DB log of the variable you have set. You could use the test page in 1 to see what exactly you have set in session for the current user.
<authentication mode="Forms">
<forms name="Web-site.ASPXAUTH" loginUrl="~/admin/login.aspx" protection="All" timeout="60" path="/" requireSSL="false" slidingExpiration="true" cookieless="UseDeviceProfile" domain="" enableCrossAppRedirects="false" />
</authentication>
<sessionState timeout="60" mode="InProc" />
<membership defaultProvider="WebSiteMembershipProvider">
<providers>
<clear />
<add name="WebSiteMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="DefaultConnStr" applicationName="web-site" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" requiresQuestionAndAnswer="false" enablePasswordReset="true" enablePasswordRetrieval="false" passwordFormat="Hashed" requiresUniqueEmail="false" />
</providers>
</membership>
<roleManager defaultProvider="WebSiteRoleProvider" enabled="true" cacheRolesInCookie="true" cookieName="Web-Site.ASPXROLES" cookieTimeout="60" cookiePath="/" cookieRequireSSL="false" cookieSlidingExpiration="true" cookieProtection="All" createPersistentCookie="false" maxCachedResults="25">
<providers>
<clear />
<add name="WebSiteRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="DefaultConnStr" applicationName="web-site" />
</providers>
</roleManager>
Related
Where’s my auth cookie gone?
When redirecting from my SSO to a client application, the .ASPXAUTH cookie is lost but only if the two sites are not on the same server.
In Fiddler, I can see the cookie being set by the SSO to the Response, in the correct cookie path for the client app. Upon redirecting however, I see that the request does not bear the cookie.
Response after logging into SSO:
Request back to client application:
Relevant sections of the Login apps web.config:
<machineKey compatibilityMode="Framework20SP2"
decryption="AES"
decryptionKey="<a valid RSA key>"
validation="SHA1"
validationKey="<a valid HMACSHA256 hash>"
/>
<!-- "SHA1" actually implements HMACSHA256, but for one reason or another, we can't specify it explicitly. -->
<authentication mode="Forms">
<forms loginUrl="Index"
cookieless="UseCookies"
requireSSL="false"
name=".ASPXAUTH"
path="/path/to/SSO-Virtual-Directory/"
slidingExpiration="true"
timeout="20"
enableCrossAppRedirects="true"
protection="All"
ticketCompatibilityMode="Framework20"
/>
<!-- set cookie path relative to virtual path of the application in IIS. See Application -> Advanced Settings to see the virtual path.
Cookie Paths, Domains, and Names are all CASE SENSITIVE!!!!!
Be sure to check the virtual path, as it doesn't update when you rename path tokens to change case. you will have to recreate the application to update the virtualpath-->
</authentication>
<!--SSOConfig Providers-->
<membership defaultProvider="SqlMembershipProvider" >
<providers>
<clear />
<add name="ADMembershipProvider"
connectionStringName="ADConnectionString"
attributeMapUsername="sAMAccountName"
enableSearchMethods="false"
connectionUsername="<a valid domain username"
connectionPassword="<a valid password>"
type="System.Web.Security.ActiveDirectoryMembershipProvider"
/>
<!-- do not set applicationName= .-->
<add name="SqlMembershipProvider"
connectionStringName="SqlConnectionString"
applicationName="SSO"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
requiresUniqueEmail="true"
passwordFormat="Hashed"
minRequiredNonalphanumericCharacters="0"
type="System.Web.Security.SqlMembershipProvider"
/>
<!-- for some messed up reason applicationName is required.-->
</providers>
</membership>
<roleManager defaultProvider="SqlRoleProvider"
enabled="true"
cacheRolesInCookie="true"
cookieName=".ASPROLES"
cookieTimeout="30"
cookiePath="/path/to/Virtual-Directory/"
cookieRequireSSL="false"
cookieSlidingExpiration="true"
cookieProtection="All"
>
<!--set cookie path relative to virtual path of the application in IIS. See Application -> Advanced Settings to see the virtual path. eg: /secure/sso/CentralLogin/ on Exodus.
Cookie Paths, Domains, and Names are all CASE SENSITIVE!!!!!
Be sure to check the virtual path, as it doesn't update when you rename path tokens to change case. you will have to recreate the application to update the virtualpath-->
<providers>
<clear />
<add name="SqlRoleProvider"
type="System.Web.Security.SqlRoleProvider"
connectionStringName="SqlConnectionString"
applicationName="SSO"
/>
<!-- set ApplicationName-->
</providers>
</roleManager>
Client Web.config:
<machineKey compatibilityMode="Framework20SP2"
decryptionKey="<The same RSA key>"
validation="SHA1"
validationKey="<The same HMACSHA256 hash>"
/>
<authentication mode="Forms" >
<forms loginUrl="~/login/Index"
name=".ASPXAUTH"
path="/Payment/"
requireSSL="false"
slidingExpiration="true"
timeout="20"
cookieless="UseCookies"
enableCrossAppRedirects="true"
protection="All"
ticketCompatibilityMode="Framework20"
/>
</authentication>
<membership defaultProvider="SqlMembershipProvider" >
<providers>
<clear />
<add name="ADMembershipProvider"
connectionStringName="ADConnectionString"
attributeMapUsername="sAMAccountName"
enableSearchMethods="true"
connectionUsername="<a valid domain username"
connectionPassword="<a valid password>"
type="System.Web.Security.ActiveDirectoryMembershipProvider"
/>
<add name="SqlMembershipProvider"
connectionStringName="SqlSSOConnection"
applicationName="SSO"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
requiresUniqueEmail="true"
passwordFormat="Hashed"
minRequiredNonalphanumericCharacters="0"
type="System.Web.Security.SqlMembershipProvider"
/>
</providers>
</membership>
<roleManager defaultProvider="SqlRoleProvider"
enabled="true"
cacheRolesInCookie="true"
cookieName=".ASPROLES"
cookieTimeout="30"
cookiePath="/Payment/"
cookieRequireSSL="false"
cookieSlidingExpiration="true"
cookieProtection="All"
>
<providers>
<clear />
<add name="SqlRoleProvider"
type="System.Web.Security.SqlRoleProvider"
connectionStringName="SqlSSOConnection"
applicationName="SSO"
/>
</providers>
</roleManager>
Both sites are MVC5 on .Net 4.5.2.
Does anyone have any ideas as to whats going wrong, and what I can do about it?
So as we seems to found out in comments, the problem is SSO and client reside on different domains\ips and so cookie set for SSO will not be passed to client by browser. There are different ways to solve this, but they require change of how your general SSO process works.
As I understand you only have problem with that in development environment, not on production. If so, suppose your SSO is on 10.0.0.1 and your client is on 127.0.0.1. Then map client.yoursite.local domain (in your corporate DNS or just in /etc/hosts file) to 127.0.0.1 and yoursite.local to 10.0.0.1, and use domain names instead of raw ip addresses. Then in SSO set cookie with domain of ".yoursite.local". This then should be delivered correctly to your client application, and will not require significant changes to how your SSO process works.
I am an active directory user and I am simply trying to print the name of the current user out in a Respnse.Write() method. From what I read from several other questions posted here I need to use
using System.Security.Principal;
string username = WindowsIdentity.GetCurrent().Name
However, when I try to write the username to the screen I get
NT AUTHORITY\NETWORK SERVICE
instead of
domain\12345678
Here is the code I am using to write to the screen:
Response.Write(WindowsIdentity.GetCurrent().Name);
and I have identity impersonate set to true in my web.config. What do I do next?
Edited to show suggested answers
my pageload
protected void Page_Load(object sender, EventArgs e)
{
string userName = User.Identity.Name;
Response.Write(userName);
//currently returning null
}
In your web.config you need authentication mode switched on to Windows and you need to disabled anonymous users
<system.web>
<authentication mode="Windows" />
<anonymousIdentification enabled="false" />
<authorization>
<deny users="?" />
</authorization>
</system.web>
The reason your approach isn't working is because User.Identity isn't physically referencing your Active Directory Membership. For all intensive purposes, is trying to grab your active user through Internet Information Systems (IIS) which it can't do in the current state. Since your utilizing Web-Forms, the easiest approach would be:
<asp:LoginView> : The following template will allow you to specify visible data for an anonymous user, logged in user, or logged out user. Which will help manage your membership system accordingly.
Membership Not Needed - Membership isn't regulated, but would like to display or access whom is logged in for certain instances.
To implement:
<connectionStrings>
<add name="ADConnectionString" connectionString="LDAP://..." />
</connectionStrings>
That will be your connectionString to your directory. Now to ensure the application authenticates correctly:
<authentication mode="Windows">
<forms loginUrl="~/Account/Login.aspx" timeout="2880" />
</authentication>
<membership>
<providers>
<clear />
<add name="MyADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ADConnectionString" />
</providers>
</membership>
Now you'll be able to properly run User.Identity.
Hopefully that helps.
string yourVariable = User.Identity.Name;
I have a web-site which uses forms auth and ActiveDirectoryMembershipProvider. I have an Action in controller like this:
[Authorize(Roles = "jira-developers")]
[HttpGet]
public ActionResult MonitorForm()
{
var list = Dal.GetActualData();
return View(list);
}
I'm totally sure that my user is in group with Name="jira-developers", but auth fails. If i remove Roles parameter, the auth will work fine.
What am i doing wrong? I'll be gratefull for any help!
As nobody gave me an answer i'll answer this question myself. ActiveDirectoryMembershipProvider can only handle auth and to enable roles management i had to specify rolesManager. I implemented my own RoleProvider (because i need some specific functionality) and now my Web.Config looks like this:
<system.web>
<authentication mode="Forms">
<forms name=".ADAuthCookie" loginUrl="~/Account/Login" timeout="45" slidingExpiration="false" protection="All" />
</authentication>
<membership defaultProvider="ADMembershipProvider">
<providers>
<clear />
<add name="ADMembershipProvider"
type="System.Web.Security.ActiveDirectoryMembershipProvider"
connectionStringName="ADConnectionString"
attributeMapUsername="sAMAccountName" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="AdRoleProvider">
<providers>
<clear/>
<add name="AdRoleProvider" type="InternalAutomation.Providers.AdRoleProvider"/>
</providers>
</roleManager>
<compilation debug="true" targetFramework="4.5.1" />
<httpRuntime targetFramework="4.5.1" />
Do you have the role defined in your Roles table? (Depending on the version you're using the table could be named slightly different than my screen shot below)
You should have an entry with a 'RoleName' of "jira-developers".
The user hitting the action should also have an entry in the '...UsersInRoles' table.
I am facing a problem,
I have set session time out in web.config
<system.web>
<sessionState timeout="60" mode="InProc" />
<httpRuntime targetFramework="4.5" />
<compilation debug="true" targetFramework="4.5" />
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
</system.web>
In my controller
public ActionResult CreateBrand()
{
Session.Timeout=60;
Purchase purchase = Session["purchaseItem"] as Purchase;
if (purchase!=null && purchase.Brand != null)
{
return View(purchase.Brand);
}
return View();
}
You never actually ask a question, so I'll take a stab at guessing what you're asking...
<sessionState timeout="60" mode="InProc" />
When mode="InProc", setting timeout="60" usually does not extend the session timeout beyond 20 minutes because the application pool will spin down (by default) after 20 minutes.
No application pool = no process = no session.
Either change your application pool settings or use a different session state provider.
I have an asp.net app with master pages. I need to have a session timeout after 10 minutes, for which I have a javascript code block. Is there any other more efficient way to do a session timeout rather than have a javascript code block on every page? (I am not using membership provider).
You can change the timeout of your session in your web.config
<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
stateNetworkTimeout="10"
sqlConnectionString="data source=127.0.0.1;Integrated Security=SSPI"
sqlCommandTimeout="30"
customProvider=""
cookieless="UseCookies"
cookieName="ASP.NET_SessionId"
timeout="10"
allowCustomSqlDatabase="false"
regenerateExpiredSessionId="true"
partitionResolverType=""
useHostingIdentity="true">
<providers>
<clear />
</providers>
</sessionState>
reference:http://msdn.microsoft.com/en-us/library/h6bb9cz9(vs.80).aspx
you can simply do this on server side. there is no point to time your session on client side. in that case, you can do it centrally on master page or webconfig or global.asax.
Using javascript is a bad idea, you can do what you want easily on the server.
Add this to your Global.asax
protected void Session_Start(object sender, EventArgs e)
{
Session.Timeout = 10;
}
And this to your web.config
<configuration>
<system.web>
<sessionState timeout="10"></sessionState>
</system.web>
</configuration>
You need to add both to make it work effectively.
You can made changes in web.config file by adding following to have session timeout:
<system.web>
<authentication mode="Forms">
<forms timeout="10"/>
</authentication>
<sessionState timeout="10" />
</system.web>
You can do it from c# by using following code:
Session.Timeout = 10;