How to properly authenticate mvc-mini-profiler with AspNetSqlMembershipProvider - asp.net

I tried to check if the user is in role at Application_BeginRequest and Application_AuthenticateRequest with this code and it will not work. At BeginRequest the code is never hit and Authenticate it's hit with some of the request and the profiler does not show up.
Checking only for Request.IsLocal works fine.
if(Request.IsAuthenticated)
{
if(User.IsInRole("Admin");
MiniProfiler.Start();
}
Any idea or why it's not working or better way to do it?
[Update] I accepted the awnser but undid it as I didn't quite get it do work
I did the following but the profiler is not showing up at first.
After a few tries it started showing up, even when I tried to acess the site with incognito mode, so no cookie.
protected void Application_PostAuthorizeRequest(Object sender, EventArgs e)
{
if (User.IsInRole("Admin"))
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("RoleProfiler");
if (cookie == null)
{
cookie = new HttpCookie("RoleProfiler");
cookie.Value = "yes";
cookie.Expires = DateTime.Now.AddDays(1d);
Response.Cookies.Add(cookie);
}
}
}
And I'm checking with
protected void Application_BeginRequest(Object sender, EventArgs e)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("RoleProfiler");
if ((cookie != null) && (cookie.Value == "yes") )
{
MvcMiniProfiler.MiniProfiler.Start();
}
}
And ending at the end of the request.
protected void Application_EndRequest()
{
MvcMiniProfiler.MiniProfiler.Stop();
}
[Update2] Closing question, ignore this, I was being owned by outputcache.

The cookie feanz mentions is a handy trick, a second method is profiling unconditionally and then abandoning the session for an unauthenticated user:
protected void Application_BeginRequest()
{
MvcMiniProfiler.MiniProfiler.Start();
}
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if(!CurrentUserIsAllowedToSeeProfiler())
{
MvcMiniProfiler.MiniProfiler.Stop(discardResults: true);
}
}

Begin request happens before the user is fully authenticated in the request life cycle.
I solved this issue by adding a cookie if the user is in a role ("Admin" in your case) when the request is authenticated then you can check for this cookie on begin request and initialise the profiler.
It wont't work the first time but should every time after that.

This is my 2cent.
context.AcquireRequestState += (sender, e) =>
{
// Check debug in session. Can be set from Querystring. (?debug=true)
if (HttpContext.Current.Session != null && HttpContext.Current.Session["Debug"] != null)
{
try{
bool debug = (bool)HttpContext.Current.Session["Debug"];
if (debug == true)
MiniProfiler.Start();
else
MiniProfiler.Stop(discardResults: true);
}
catch{
MiniProfiler.Stop(discardResults: true);
}
}// Or always show if Administrator.
else if (HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated)
{
bool admin = HttpContext.Current.User.IsInRole("Administrator");
if (admin == false)
{
MiniProfiler.Stop(discardResults: true);
}
}
else
{
MiniProfiler.Stop(discardResults: true);
}
};

Related

How to clear ALL active sessions in asp.net

1) I'd like to know how can I clear all sessions in asp.net so every user logged to a system can't work unless they log-in again.
2) Is there any way to iterate through all sessions to make an exception for admin users stored in session?
Thanks in advance!
Regards.
You cannot access Session state from within another session however you can share data via the Application state and use that to kill other sessions when they next do a request via Global.asax
Keep track of time when each session was started via Session_Start in Global.asax
void Session_Start(object sender, EventArgs e)
{
// Code that runs when a new session is started
Session["dtmStart"] = DateTime.Now;
}
Abandon each session when it next requests via Application_AcquireRequestState in Global.asax if the session was started before the current kill time stored in Application state
void Application_AcquireRequestState(object sender, EventArgs e)
{
// Occurs as the first event in the HTTP pipeline chain of execution when ASP.NET responds to a request.
// Check if session should be killed
if (Application["dtmClearSessions"] != null
&& Session["dtmStart"] != null
&& (DateTime)Application["dtmClearSessions"] > (DateTime)Session["dtmStart"])
{
// Check if user is an administator
if (Application["lstAdminUserIds"] != null && Session["intMyUserId"] != null)
{
List<int> lstAdminUserIds = (List<int>)Application["lstAdminUserIds"];
int intMyUserId = (int)Session["intMyUserId"];
if (lstAdminUserIds.Contains(intMyUserId))
return;
}
Session.Abandon();
}
}
To flag that the sessions should be abandoned simply set Application["dtmClearSessions"] = DateTime.Now; for example via a button press on a page.
protected void btnKillEmAll_Click(object sender, EventArgs e)
{
try
{
Application["dtmClearSessions"] = DateTime.Now;
}
catch (ThreadAbortException ex) { throw ex; }
catch (Exception ex)
{
// TODO: RecordError(ex, "my_page.btnKillEmAll_Click", Request);
// TODO: show error on screen litError.Text = ex.Message;
}
}

Two virtual directories on IIS for secured pages

I am developing application in .net 4.0.In my web application project it have secured folder.
now i want to redirect only authenticated users to secured pages.
i want to do this making two different virtual directories on IIS.(Virtual directory within one more directory)
can i do this? how can i do this? or is there any way to this?
Thanks in advanced.
If you like to do that manually with your code, the right place is on global.asax the Application_AuthenticateRequest trigger. Here is an example, and you can change it according to your logic.
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
string cTheFile = HttpContext.Current.Request.Path;
if(!cTheFile.Contains("/securedir/"))
{
if (HttpContext.Current.Request.IsSecureConnection)
{
HttpApplication app = (HttpApplication)sender;
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
// if this is null, then the user is not logged in
if (null == authCookie)
{
// for the same check you can also use
//if(HttpContext.Current.User == null || HttpContext.Current.User.Identity == null || !HttpContext.Current.User.Identity.IsAuthenticated)
string sExtentionOfThisFile = System.IO.Path.GetExtension(cTheFile);
if (sExtentionOfThisFile.Equals(".aspx", StringComparison.InvariantCultureIgnoreCase))
{
Response.Redirect("/", true);
Response.End();
// There is no authentication cookie.
return;
}
}
}
}
}
}

Accessing Sessions Variables in code behind

Here is my code:
protected void Page_Load(object sender, EventArgs e)
{
if (!Session["Authenticated"] )
{
Response.Redirect( "index.aspx", false );
}
}
Once they login I set the session to true. Basically, if they don't have an active session I want them re-directed back to the index/login page. How do I accomplish this?
Use this check
if(Session["Authenticated"] == null || !(bool)Session["Authenticated"])
If you are using cookie, you can store a marker in your cookie so you can tell the difference between "fresh browser + new session" and "old browser + expired session".
Below is sample code that will redirect the user to an expired page if the session has expired.
void Session_OnStart(Object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
HttpCookieCollection cookies = context.Request.Cookies;
if (cookies["starttime"] == null) {
HttpCookie cookie = new HttpCookie("starttime", DateTime.Now.ToString());
cookie.Path = "/";
context.Response.Cookies.Add(cookie);
}
else {
context.Response.Redirect("expired.aspx");
}
}
And if you are trying to implement sessions this might help you http://aspalliance.com/1621_Implementing_a_Session_Timeout_Page_in_ASPNET.2

Login control - error

There is a Login control on my ASP.NET (2.0) page. I handle LoggingIn event like this:
protected void Login1_LoggingIn(object sender, LoginCancelEventArgs e)
{
// go to database and find this user
if (userTable != null && userTable.Rows.Count > 0)
{
int userID = Convert.ToInt32(userTable.Rows[0]["UserID"]);
HttpCookie userIdCookie = new HttpCookie("UserID", userID.ToString());
Response.AppendCookie(userIdCookie);
}
else
{
e.Cancel = true;
}
}
User found in database. And at the end of this function e.Cancel still set to false. But then occured LoginError. LoggedIn doesn't occured. And FailureText appears on the page. I don't know how to debug this :(
Have you also handled the Authenticate event?
<asp:Login id="Login1" runat="server"
OnAuthenticate="MyOnAuthenticate">
private void MyOnAuthenticate(object sender, AuthenticateEventArgs e)
{
bool isAuthenticated = false;
isAuthenticated = YourAuthenticationMethod(Login1.UserName, Login1.Password);
e.Authenticated = isAuthenticated;
}
private bool YourAuthenticationMethod(string UserName, string pwd)
{
// Insert code that implements a site-specific custom
// authentication method here.
}
LoginControl's Authenticated event on MSDN

ASP.NET Forms Authentication with Windows Safari

Does anyone know why ASP.NET Forms Authentication does not work on windows safari, or better yet, how to get it to work? It seems like a very weird issue. When I use a login control (System.Web.UI.WebControls.Login) everything works fine, but if I try to do a custom Forms Authentication login when I call FormsAuthentication.RedirectFromLoginPage safari just sends me back to the login page as if I'm not authenticated whereas every other browser logs me in and sends me on my way.
protected void lnkLogin_Click(object sender, EventArgs e)
{
if (Membership.Provider.ValidateUser(txtUsername.Text, txtPassword.Text))
{
Session.Clear();
HttpContext.Current.Response.Cookies.Clear();
FormsAuthentication.SetAuthCookie(txtUsername.Text, true);
FormsAuthentication.RedirectFromLoginPage(txtUsername.Text, true);
}
}
Try either SetAuthCookie, or RedirectFromLoginPage. The redirect needs to know where to redirect to anyway (ReturnUrl), maybe that is your problem.
if (Request.QueryString["ReturnUrl"] != null)
{
FormsAuthentication.RedirectFromLoginPage("someuserid", false);
}
else
{
FormsAuthentication.SetAuthCookie("someuserid", false);
Response.Redirect("~/SomePage.aspx");
}
This works fine for me in Safari:
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
//check login
User user = UserBAL.GetUser(Login1.UserName, Login1.Password);
//null and filled object check
if (user != null && user.Id > 0 && user.Roles != null && user.Roles.Count > 0)
{
e.Authenticated = true;
FormsAuthenticationTicket authTicket = new
FormsAuthenticationTicket(1, //version
Login1.UserName, // user name
DateTime.Now, // creation
DateTime.Now.AddMinutes(60),// Expiration
false, // Persistent
string.Join("|", user.Roles.ToArray())); // User ata
// Now encrypt the ticket.
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
// Create a cookie and add the encrypted ticket to the
// cookie as data.
HttpCookie authCookie =
new HttpCookie(FormsAuthentication.FormsCookieName,
encryptedTicket);
Response.Cookies.Add(authCookie);
//redirect
Response.Redirect(FormsAuthentication.GetRedirectUrl(
Login1.UserName,
false));
}
else
{
Login1.FailureText = "Login failed.";
}
}

Resources