I have an asp.net webforms project. In there, an "Admin" has the ability to get to a screen to submit a form that will create a new user (CreateUser.aspx).
If that user's permission is changed later to be less than Admin they can't access that screen anymore to create new users. However, if they saved the exact web request to create a new user from when they were an admin, they can replay this and create new users still.
It is not possible for a random person to submit this form though unless they guess an active session id (that is the only thing checked on each form submit).
CreateUser is one of many examples of admin functions. Is the proper solution to this to validate that the user is an admin on each of these different form submits (not sure of a clean way to do this in asp.net)? Or is it acceptable to just expire the session on logout and never reuse session id's? Does asp.net have any other security features built-in to protect against this type of attack?
One way, is to have a base class(Which inturn inherits the class - "page") and all your aspx pages should inherit this base class. so that whenever a aspx page loads, your base pageLoad method is called. In this method you can check the authentication and authorization.
public class BasePage : System.Web.UI.Page
{
public BasePage()
{
this.Load += new EventHandler(BasePage_Load);
}
void BasePage_Load(object sender, EventArgs e)
{
//Check authentication/authorized
//if authenticated/authorized leave it.. If not redirect to error page
}
}
public partial class Forms_CreateUser : BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
public partial class Forms_CreateRole : BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
User web.config's Authorization settings to restrict access to CreateUser.aspx to users in the admin role: http://support.microsoft.com/kb/316871 (attribute name is roles instead of users).
Related
I’ve made a handy “user control” for login to my website and it is placed in the site master.
The natural procedure is that the user logs in the web site and he should be announced with a welcome message containing its full name. The full-Name naturally should sits in a session variable created when the user logged on.
There is no doubt that we place the desired code in the “page_load” event and expect it to pass user’s full-name to the right circumstances (here its a label named lblFullName) in order to print/show the welcome message when login button clicked, But the full-name doesn’t passed until the user logs in the website again (for the 2nd times).
Why this problem happens?
Its some part of my code:
protected void Page_Load(object sender, EventArgs e)
{
if (Session["FullName"]==null)
{
//nothing 2 do.
}
else
{
lblFullName.Text = Session["FullName"].ToString();
}
}
You probably set the Session variable in the user control after the Page_Load event has been processed, so that it will not see the user name until the next postback.
In order to update the Label text as soon as the login is validated, you could:
Define an event in the user control
Register an event handler in the main page
Call the event handler as soon as the user has logged in
In the event handler, update the Label text
You could also eliminate the Session variable by passing the user full name in an EventArgs derived class. If you make the following class accessible in the user control and in the main form:
public class StringEventArgs : EventArgs
{
public string Value { get; set; }
public StringEventArgs(string value)
{
Value = value;
}
}
then you can define this event in the user control:
public event EventHandler<StringEventArgs> UserLoggedIn;
In the function where the login is confirmed, you call the event handlers:
private void UserLoginValidation()
{
// Login validation is done here
bool loginSuccessful = ...
if (loginSuccessful && UserLoggedIn != null)
{
UserLoggedIn(this, new StringEventArgs(fullName));
}
}
In the main page, you register the event handler, which updates the Label:
protected void Page_Load(object sender, EventArgs e)
{
loginUserControl1.UserLoggedIn += loginUserControl1_UserLoggedIn;
...
}
private void loginUserControl1_UserLoggedIn(object sender, StringEventArgs e)
{
lblFullName.Text = e.Value;
}
I have a data driven website and the current users Id gets stored in Session["UserId"].So all the data that shows up in almost all the pages is user specific.and when a user is using the site anonymously,it is a different set of results that i show and has nothing to do with the UserId.
My problem is I have to check if the Session["UserId"] is not null at every line where I am using Session["UserId"] and i somehow feel that it is not the right way to do it.
Is there a way where I can check if the Session is not null on page_load? If my session turns out to be null, how do i handle it? the page won't even load at all.
I hope i was able to explain
Instead of check session on every of your pages, put the session control in a base class and make all your pages extends this class. Every time your page inits the Page_Init base method will check if user is authenticated. If it's not authenticated the method will throw an exception that will be catched by Page_Error method. This method will clear session resources and redirect to Default page.
Make a hyerarchical classes for session control:
public class UserSession { }
public class AnonymousSession : UserSession {}
On your Page Logon put the UserId on the session based on logon type:
bool isAnon = GetAnonymous(); // Check form page if login is anonymously
UserSession user;
if(isAnon)
user = new AnonymousSession();
else
user = new UserSession();
Session.Contents.Add("UserId", user);
Set a property in PageBase named Anonymously that tells you if user has entered anonymously, and use it in your pages to set the set results of each of your pages:
public class PageBase: System.Web.Ui.Page
{
// Check here if session type is anonymous
protected bool Anonymously
{
get
{
return (UserSession)Session.Contents["UserId"] is AnonymousSession;
}
}
protected void Page_Init(object Sender,System.EventArgs e)
{
var user = (UserSession)Session.Contents["UserId"];
if (user == null)
{
throw new SessionException();
}
}
protected void Page_Error(object sender, System.EventArgs e)
{
Exception ex = Server.GetLastError();
Server.ClearError();
if(ex is SessionException)
{
Context.Session.Clear();
Context.Session.Abandon();
FormsAuthentication.SignOut();
Server.Transfer("Default.aspx", true);
}
}
}
I developed a HttpModule for assigning themes to pages during it's PreInit event from Profile of the logged in user. But seems the profile is not initialized at the time i access it. Is there a specific event after which i should access Profile for a user similar to access page cotnrols after Init event. btw i am running on ASP.NET 2.0 and Custom Profile Provider implementation.
public void CurrentPageOnPreInit(object sender, EventArgs e)
{
//Get the page currently requested
Page currentPage = (Page)sender;
//Get the user profile
ProfileCommon userProfile = HttpContext.Current.Profile as ProfileCommon;
//check if user profile has theme set
if (userProfile != null && !string.IsNullOrEmpty(userProfile.Theme))
{
//retrieve from profile
currentPage.Theme = userProfile.Theme;
where the above method executes on PreInit stage of each page on my application.
It needs to initialized in the OnPreInit method of the class.
override void OnPreInit(EventArgs e);
For methods execution follow this link it give brief about when which method will call asp.net life cycle.
What i am doing is whenever users logs in I store his username in Session Object
Now what i want on the Admin Page is the List of ACTIVE USERS (i.e No of Users which are presently working with the Application (usernames in Session Objects)
Is there any way of doing that..
???
Thanks
Based on your comment to Davide Piras, if you are storing Session["user"] =username then you are only storing one element since you are always using the same key.
I would put everything in a List<string>, for example.
Something like this in your login page:
List<string> activeUsers = Cache["ActiveUsers"] as List<string>;
if(activeUsers==null)
activeUsers = new List<string>();
activeUsers.Add(username_of_person_logged_in);
Cache["active_users"]=activeUsers;
Then in your "Admin" page...
List<string> activeUsers = Cache["ActiveUsers"] as List<string>;
if(activeUsers!=null)
{
foreach(var item in activeUsers)
{
//do something with them
}
}
Note: I changed it to Cache since Cache is shared across all users. Session will not work since it will be only valid on a per-user basis. Thanks to #CheckRaise for his comment.
The Session object cannot be accessed outside of its own session. If you need an administrator to be able to see all the active sessions, you need to use the Application object. For example, in global.asax:
protected void Application_Start(object sender, EventArgs e) {
Application["Users"] = new List<string>;
}
Then, to add a user (possibly when they click 'Log in'):
Application.Lock();
((List<string>)Application["Users"]).Add(username);
Application.UnLock();
You should also remove the user in Session_End:
protected void Session_End(object sender, EventArgs e) {
Application.Lock();
((List<string>)Application["Users"]).Remove(username);
Application.UnLock();
}
Currently, I'm just using clientside Javascript (location.href), but I am wondering if there is a way in Asp.Net to figure out the URL the user originally entered (assume I did not change it myself via 301), or at least to track it in a simple and reliable manner. As I am using my own implementation of URL rewriting via the global.asax (e.g. Context.RewritePath), this is not an easy task, particularly since I don't want to touch it too much.
Example
Global.asax:
public override void Init()
{
base.Init();
this.BeginRequest += new EventHandler(Global_BeginRequest);
}
void Global_BeginRequest(object sender, EventArgs e)
{
if (VARIOUSCONDITIONS) Context.RewritePath("SOMEURL");
}
SomePage.aspx.cs
protected void Page_Init(object sender, EventArgs e)
{
//Request.RawUrl is equal to "SOMEURL", as
//are other properties that store the URL.
}
Maybe I am misunderstanding your question, but if you are trying to capture the page the user first hits on your website, cant you capture this in the session_start event of global.asax? Then store in sessionstate or database for future use?