I am working on an ASP.NET MVC 5 web application, and I am using forms authentication against our LDAP server.
Here is the login action method:-
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
MembershipProvider domainProvider;
domainProvider = Membership.Providers["ADMembershipProvider"];
if (ModelState.IsValid)
And the related entities inside our web.config file, which connects to the LDAP:
<providers>
<add name="ADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="TestDomain1ConnectionString" connectionUsername="ad.user" connectionPassword="***" attributeMapUsername="sAMAccountName"/>
</providers>
<connectionStrings>
<add name="TestDomain1ConnectionString" connectionString="LDAP://ad-Tgroup.intra/OU=T,DC=ad-Tgroup,DC=intra"/>
</connectionStrings>
Currently I am storing the domainname\username inside our log table, as follows:
string ADusername = User.Identity.Name.ToString();
repository.InsertOrUpdateResturant(resturant, ADusername);
Using the User.Identity.Name might work in almost 95% of the cases because it can uniquely identify any user, but on the other hand, the username might be changed (let's say a user got married or divorced). So I am planning on replacing my User.Identity.Name and getting the user GUID instead. But I'm not sure if MVC 5 provides a way to get the login user GUID. For example, I cannot write User.Identity.GUID.
Related
In my post action, I simple put the simple code as follows:
[HttpPost]
public ActionResult Test()
{
Session["mykey"] = DateTime.Now.ToString("HH:ss");
System.Threading.Thread.Sleep(120000);
return View();
}
In debugging, when I clicked on the submit button, the Session contained correct value. But when I submitted again, the Session did not contain "mykey"(Session["mykey"] is null).
This did not happen if I removed Thread.Sleep method or set the short time (e.g. System.Threading.Thread.Sleep(10000))
The config setting in my application is as follows:
<sessionState mode="Custom" customProvider="MySessionStateStore">
<providers>
<add name="MySessionStateStore" type="Microsoft.Web.Redis.RedisSessionStateProvider"
host="myhost.cache.windows.net" port="6380"
accessKey="myaccesskey"
ssl="true" />
</providers>
</sessionState>
Could you please give me your ideas? Thank you!
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.
I just don't get how these two potentially incredibly useful functions are supposed to work.
[Authorize(Roles="Admin")] //Method A
and
User.isInRole("Admin") //Method B
They are clearly not working right now for me. I did a few hours of research:
I read that you need to implement System.Web.Security.RoleProvider, then set it up in the web config:
<roleManager defaultProvider="OdbcRoleProvider"
enabled="true"
cacheRolesInCookie="true"
cookieName=".ASPROLES"
cookieTimeout="30"
cookiePath="/"
cookieRequireSSL="false"
cookieSlidingExpiration="true"
cookieProtection="All" >
<providers>
<clear />
<add
name="OdbcRoleProvider"
type="Samples.AspNet.Roles.OdbcRoleProvider"
connectionStringName="OdbcServices"
applicationName="SampleApplication"
writeExceptionsToEventLog="false" />
</providers>
</roleManager>
This caused the RoleProvider I implemented to by constructed, but the role checking functions were certainly not calling any of the methods in there.
I then read that Asp.NET Identity does away with the RoleProvider, now you need to do this:
<modules runAllManagedModulesForAllRequests="true">
<remove name="FormsAuthenticationModule" />
<remove name="RoleManager" />
</modules>
And I did that.
I have a custom UserManager that connects to my postgres backend. The problem is that whenever I use it, I need to instantiate one. It seems to me that if Functions A and B are going to work, then the UserManager I have implemented needs to be referenced in some sort of config file so Asp.NET knows about it implicitly. This would be just like the RoleManager in the past.
How does ASP.NET identity alter how Functions A and B check the roles from the old RoleProvider using behavior?
I figured it out.
When you call the login code like this:
var user = await UserManager.FindAsync(model.Email, model.Password);
if (user != null && user.PasswordRequiresReset == false)
{
await SignInAsync(user, model.RememberMe); //triggers IUserRoleStore.GetRolesAsync
return RedirectToLocal(returnUrl);
}
SignInAsync triggers GetRolesAsync from the IUserRoleStore:
public Task<IList<string>> GetRolesAsync(TUser user) //where TUser is an ApplicationUser
{
Func<object, IList<string>> getRoles = (object user2) =>
{
TUser user3 = (TUser)user2;
return user3.Roles.Select(x => x.Role.Name).ToList();
};
return Task.Factory.StartNew(getRoles, user);
}
In the above, I chose to simply generate the roles from the roles I already loaded from the db and stored in the ApplicationUser object when I created it in FindAsync.
The roles from GetRolesAsync must be loaded in the cookie somewhere where they can be accessed quickly and easily by Functions A and B.
We have an intranet ASP.NET 4.0 application and use forms authentication where employees authenticate against Active Directory to log in.
We need to lock users out of AD after too many failed password attempts (number is set in domain policy).
As it works now, users get locked out of the application only but not out of AD. We need to lock them in AD and they will need to call help desk to unlock them.
I saw this http://msdn.microsoft.com/en-us/library/ms998360.aspx, where it is stated under "Account Lockout" that ActiveDirectoryMembershipProvider locks users out of provider but not out of AD.
But how do we lock users in AD then?
web.config:
<membership defaultProvider="MyADMembershipProvider">
<providers>
<add name="MyADMembershipProvider"
type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="ADConnectionString"
connectionUsername="administrator"
connectionPassword="passw0rd"
attributeMapUsername="sAMAccountName" />
</providers>
</membership>
Login.aspx:
<asp:Login ID="Login1" runat="server" DisplayRememberMe="False" FailureText="Wrong user name or password." DestinationPageUrl="~/User.aspx" OnLoggedIn="Login1_LoggedIn" OnLoginError="Login1_LoginError">
Login.aspx.cs
protected void Login1_LoginError(object sender, EventArgs e)
{
string userName = Login1.UserName;
if (!string.IsNullOrEmpty(userName))
{
// Get information about this user
MembershipUser usr = Membership.GetUser(userName);
if (usr != null)
{
// check to see if the error occurred because they are not approved
if (!usr.IsApproved)
{
Login1.FailureText = "Your account has not yet been approved by an administrator.";
}
// check to see if user is currently locked out
else if (usr.IsLockedOut)
{
Login1.FailureText = "You have been locked out of your account due to too many failed passwords. Call help desk to unlock it.";
}
}
}
}
By default ASP.NET Identity user data is stored in an mdf file.
I want to store the data in a Sql database so that I changed the defaultconnection string in my web.config to my EF based connection:
<add name="DefaultConnection" connectionString="metadata=res://*/Models.StartifyModel.csdl|res://*/Models.StartifyModel.ssdl|res://*/Models.StartifyModel.msl;provider=System.Data.SqlClient;provider connection string="data source=MYPC\SQLEXPRESS;initial catalog=mydb;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
Now I am getting the error The entity type ApplicationUser is not part of the model for the current context. as soon as I want to register a user.
I use the default MVC5 project template of VS2013.
Please try specify the connection string in the format:
<add name="DefaultConnection" connectionString="Data Source=127.0.0.1, 1433;Initial Catalog=YourDB;User Id=XXXX;Password=XXXXX;Asynchronous Processing=True;Encrypt=False;TrustServerCertificate=True;Persist Security Info=True" providerName="System.Data.SqlClient" />
And then make sure in Models/IdentityModels.cs you have
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}