PDA

Click to See Complete Forum and Search --> : Form based authentication question


mpSmooth
May 10th, 2003, 08:33 PM
On my intial page that displays I do not perform any type of security (form based). However, I have a add user button on the same screen, and when the user clicks on the button, I want to invoke the form based authentication, so I can redirect the user to the login screen. Any ideas on how to do this?

hellswraith
May 10th, 2003, 09:12 PM
In your button click event do something like this:

if(!HttpContext.Current.User.Identity.IsAuthenticated)
{
Response.Redirect("LoginPage.aspx");
return;
}
// Rest of code if authenticated goes here.

mpSmooth
May 10th, 2003, 09:52 PM
Thats the problem I'm having, when I redirect, after I successfully login, it throws this error:


Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.


It seems that it is not able to remember what page it came from

hellswraith
May 10th, 2003, 10:14 PM
I have had that problem myself. What I do is set a session variable before I redirect with the page the person is currently at. After successful login, I check the session variable and see if the value is there (it could be null if it came from some other page). If the value is there, I redirect the user to that value (page).

So before I send them to the login page, I set the session variable:

Session["PageCameFrom"] = Request.Path.ToString() + "?" + Request.QueryString.ToString();
// Send to login page.
Response.Redirect("Login.aspx");

You don't need the query string part if you are not using query strings, but it doesn't hurt to leave it on anyway.

Next after successful login in the login page code, I check the variable to see if it contains a url to redirect to. If it does, I send them to that url, if not, let the application do the work it was intended to do (or send them to a common page in the application.

// Redirect the user to where they came from.
if(Session["PageCameFrom"] != null)
{
Response.Redirect(Session["PageCameFrom"].ToString());
return;
}
else
{
// This is optional, I do this though because I don't let the
// application handle redirects.
Response.Redirect("Index.aspx");
return;
}

mpSmooth
May 10th, 2003, 10:33 PM
It blows up on this line:


FormsAuthentication.RedirectFromLoginPage(UserName.Text,(bool)PersistPassword.Checked);

hellswraith
May 10th, 2003, 10:37 PM
Ok, I don't know a way around that except if you took the authentication into your own hands and created your own routine to verify the user, create a ticket, and assign the principle object the ticket.

If you want, I can post the code i use to authenticate users. You can check it out in action at my forums:
www.variantx.com/vxforums/

mpSmooth
May 10th, 2003, 11:00 PM
could you post the code?

hellswraith
May 10th, 2003, 11:04 PM
Up to you to make sense of it...lol.

My Login page code when they click the login button (Assumes a username textbox, password textbox, and a checkbox to see if the user wants to stay logged in from that computer):

private void LogonButton_Click(object sender, System.EventArgs e)
{
// Get the application variables.
string bannedMessage = "You have been banned from posting on this forum.";
string logonIncorrect = "Your login information is incorrect.";


string roles;
bool keepLoggedIn = KeepLoggedInCheckBox.Checked;

DataAccess.Security sec = new DataAccess.Security();
DataAccess.User uo = new DataAccess.User();
DataRow dr = uo.RetrieveFromUserName(HttpUtility.HtmlEncode(UserNameTextBox.Text.Trim()));


// Obtain the roles the user is allowed to use.
roles = sec.GetUserRoles(HttpUtility.HtmlEncode(dr["UserName"].ToString()), PasswordTextBox.Text);

// If the login was correct, the user should have at least one role.
if(!(roles.Length > 0))
{
// No roles were returned, need to let the user know the login
// was incorrect.
MessageLabel.Font.Bold = true;
MessageLabel.Text = logonIncorrect;
MessageLabel.Visible = true;
return;
}

// Check to see if the user validated their email address.
if(!uo.EmailVerified(HttpUtility.HtmlEncode(dr["UserName"].ToString())))
{
// The users email hasn't been verified yet, need to get them
// to verify it.
Session["PageCameFrom"] = Request.Path.ToString() + "?" + Request.QueryString.ToString();
Response.Redirect("VerifyEmail.aspx");
return;
}

if(uo.IsUserBanned(HttpUtility.HtmlEncode(dr["UserName"].ToString())))
{
MessageLabel.Font.Bold = true;
MessageLabel.Visible = true;
MessageLabel.Text = bannedMessage;
return;
}

if(!keepLoggedIn)
{
// Create a new ticket with the roles attached, this one expires in 30 minutes.
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, HttpUtility.HtmlEncode(dr["UserName"].ToString()), DateTime.Now, DateTime.Now.AddMinutes(30), true, roles, FormsAuthentication.FormsCookiePath);

// Encrypt the ticket and create a cookie with it.
string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);

// Add the cookie to the users computer.
Response.Cookies.Add(cookie);

// Redirect the user to where they came from.
if(Session["PageCameFrom"] != null)
{
Response.Redirect(Session["PageCameFrom"].ToString());
return;
}
else
{
Response.Redirect("Index.aspx");
return;
}
}
else
{
// Need to persist the cookie so everytime the user
// returns they don't have to log in.
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, HttpUtility.HtmlEncode(dr["UserName"].ToString()), DateTime.Now, DateTime.Now.AddMonths(6), true, roles, FormsAuthentication.FormsCookiePath);

string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
Response.Cookies.Add(cookie);

if(Session["PageCameFrom"] != null)
{
Response.Redirect(Session["PageCameFrom"].ToString());
return;
}
else
{
Response.Redirect("Index.aspx");
return;
}
}
}


And in the Global.asax file I have this:

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if(HttpContext.Current.User != null)
{
// Check to see if the user is banned.
DataAccess.User uo = new DataAccess.User();

if(!uo.IsUserBanned(HttpContext.Current.User.Identity.Name))
{
if(HttpContext.Current.User.Identity.IsAuthenticated)
{
if(HttpContext.Current.User.Identity.GetType() == typeof(FormsIdentity))
{
FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
string userData = ticket.UserData;
string[] roles = userData.Split(',');
HttpContext.Current.User = new GenericPrincipal(id, roles);
}
}
}
else
{
HttpContext.Current.User = null;
}
}
}


I am having a problem though. For some reason, the user is not remembered next time they come back like they should be. I add six months to the cookies expiration date, but it doesn't work. I have to read through some documentation to get that working right. Probably something I am missing. But for the actual logging it, it works fine, and while you are using it, it stays logged in.

I have this object/function that returns a comma delimited string of roles. That is how my security is ran. So that
sec.GetUserRoles(HttpUtility.HtmlEncode(dr["UserName"].ToString()), PasswordTextBox.Text)
function takes in the username and password, and verifies they match up and gets the roles for that user. You would have to implement that functionality.

jesus4u
Jun 10th, 2003, 12:01 PM
Originally posted by hellswraith
Up to you to make sense of it...lol.

My Login page code when they click the login button (Assumes a username textbox, password textbox, and a checkbox to see if the user wants to stay logged in from that computer):

private void LogonButton_Click(object sender, System.EventArgs e)
{
// Get the application variables.
string bannedMessage = "You have been banned from posting on this forum.";
string logonIncorrect = "Your login information is incorrect.";


string roles;
bool keepLoggedIn = KeepLoggedInCheckBox.Checked;

DataAccess.Security sec = new DataAccess.Security();
DataAccess.User uo = new DataAccess.User();
DataRow dr = uo.RetrieveFromUserName(HttpUtility.HtmlEncode(UserNameTextBox.Text.Trim()));


// Obtain the roles the user is allowed to use.
roles = sec.GetUserRoles(HttpUtility.HtmlEncode(dr["UserName"].ToString()), PasswordTextBox.Text);

// If the login was correct, the user should have at least one role.
if(!(roles.Length > 0))
{
// No roles were returned, need to let the user know the login
// was incorrect.
MessageLabel.Font.Bold = true;
MessageLabel.Text = logonIncorrect;
MessageLabel.Visible = true;
return;
}

// Check to see if the user validated their email address.
if(!uo.EmailVerified(HttpUtility.HtmlEncode(dr["UserName"].ToString())))
{
// The users email hasn't been verified yet, need to get them
// to verify it.
Session["PageCameFrom"] = Request.Path.ToString() + "?" + Request.QueryString.ToString();
Response.Redirect("VerifyEmail.aspx");
return;
}

if(uo.IsUserBanned(HttpUtility.HtmlEncode(dr["UserName"].ToString())))
{
MessageLabel.Font.Bold = true;
MessageLabel.Visible = true;
MessageLabel.Text = bannedMessage;
return;
}

if(!keepLoggedIn)
{
// Create a new ticket with the roles attached, this one expires in 30 minutes.
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, HttpUtility.HtmlEncode(dr["UserName"].ToString()), DateTime.Now, DateTime.Now.AddMinutes(30), true, roles, FormsAuthentication.FormsCookiePath);

// Encrypt the ticket and create a cookie with it.
string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);

// Add the cookie to the users computer.
Response.Cookies.Add(cookie);

// Redirect the user to where they came from.
if(Session["PageCameFrom"] != null)
{
Response.Redirect(Session["PageCameFrom"].ToString());
return;
}
else
{
Response.Redirect("Index.aspx");
return;
}
}
else
{
// Need to persist the cookie so everytime the user
// returns they don't have to log in.
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, HttpUtility.HtmlEncode(dr["UserName"].ToString()), DateTime.Now, DateTime.Now.AddMonths(6), true, roles, FormsAuthentication.FormsCookiePath);

string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
Response.Cookies.Add(cookie);

if(Session["PageCameFrom"] != null)
{
Response.Redirect(Session["PageCameFrom"].ToString());
return;
}
else
{
Response.Redirect("Index.aspx");
return;
}
}
}


And in the Global.asax file I have this:

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if(HttpContext.Current.User != null)
{
// Check to see if the user is banned.
DataAccess.User uo = new DataAccess.User();

if(!uo.IsUserBanned(HttpContext.Current.User.Identity.Name))
{
if(HttpContext.Current.User.Identity.IsAuthenticated)
{
if(HttpContext.Current.User.Identity.GetType() == typeof(FormsIdentity))
{
FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
string userData = ticket.UserData;
string[] roles = userData.Split(',');
HttpContext.Current.User = new GenericPrincipal(id, roles);
}
}
}
else
{
HttpContext.Current.User = null;
}
}
}


I am having a problem though. For some reason, the user is not remembered next time they come back like they should be. I add six months to the cookies expiration date, but it doesn't work. I have to read through some documentation to get that working right. Probably something I am missing. But for the actual logging it, it works fine, and while you are using it, it stays logged in.

I have this object/function that returns a comma delimited string of roles. That is how my security is ran. So that
sec.GetUserRoles(HttpUtility.HtmlEncode(dr["UserName"].ToString()), PasswordTextBox.Text)
function takes in the username and password, and verifies they match up and gets the roles for that user. You would have to implement that functionality.

Which namespace is DataAccess.Security tied to???