This might sound like a stupid question, but I am about to implement a custom security database and framework for a new site. I was wondering how best to handle this.
NOTE: I am NOT using the ASP.NET Membership for this, I am using a custom database and everything custom for user management.
There will be several levels of security, so I am a bit stumped on this without making it too difficult. The only thing I could think of so far is check on EVERY PAGE in the Page_Load if they have the right security:
protected void Page_Load(object sender, EventArgs e)
{
CustomUser user = Session["User"] as CustomUser;
if(user != null && user.CanAccessFeature("TopicModeration"))
{
//initialize page elements
}
else
{
Response.Redirect("Default.aspx?featureDenied=TopicModeration", false);
Context.ApplicationInstance.CompleteRequest();
}
}
That works fine, but if I have dozens of pages that have different restrictions, it can get a bit repetitive. Does anybody have any thoughts on this? Should I inherit from System.Web.Page for each security feature, and use that on the page instead?
Thanks!
May i suggest the following approach:
Create a custom controller class as such:
public class CustomController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
CustomUser user = Session["User"] as CustomUser;
if(user != null && user.CanAccessFeature("TopicModeration"))
{
base.OnActionExecuting(filterContext);
}
else
{
filterContext.Result = new RedirectResult("Default.aspx?featureDenied=TopicModeration", false);
Context.ApplicationInstance.CompleteRequest();
}
}
}
Then you may have your controllers where you want that check to inherit from this controller.
You can create a Base Class and make all master pages (or pages) inherit that class.
Here is an example when a Master Page inherits a class.
Class for all master pages to inherit.
public class PageBase: System.Web.UI.MasterPage
{
protected override void OnLoad(EventArgs e)
{
//Put your security code here...
base.OnLoad(e);
}
}
Here is a Master page inheriting the class above.
public partial class Site1ColMaster : MySite.PageBase
{
protected void Page_Load(object sender, EventArgs e)
{
//Master page
}
}
Related
I have an application in which when user login page load event check either there is a session for this user or not if there is no session user redirect to login.aspx file. But my web application has a lot of pages so instead of writing session code in every page load event I want to call it in page load event so I want to ask can I add this code in web.config file if yes then please help me how can I do this?
Thanks
if (Session["LoginUserName"] != null)
{
string str;
str = Session["LoginUserName"].ToString();
Label1.Text = str;
}
else
{
Server.Transfer("Login_Form.aspx");
}
make you all your Pages code inherit from a custom Class. Instead of the original class System.Web.UI.Page
Do it for all ASPX pages
public partial class MyPage : PageCommonBase
{
....
}
Make your custom class PageCommonBase and check for SessionUser OnPreinit Event
public class PageCommonBase : System.Web.UI.Page
{
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
if (
HttpContext.Current.Session.IsNewSession ||
HttpContext.Current.Session["LoginUserName"] == null
)
{
......
}
else
.....
}
}
I have read that an effective way to use enable session in web api 2 is like so:
protected void Application_PostAuthorizeRequest()
{
System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.ReadOnly);
}
I have also created a class that inherits from AuthorizationFilterAttribute and overrides the OnAuthorization method.
But this event is never called - what am I doing wrong?
You could try creating a HttpModule:
public class WebApiSessionModule : IHttpModule
{
protected virtual void OnPostAuthorizeRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
if (this.IsWebApiRequest(context))
{
context.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.ReadOnly);
}
}
}
You'll need to add this to your web.config in
<system.web>
<httpModules>
On reading about preventing cross-site request forgeries in webforms many authors use statements like this:
To use the ViewStateUserKey property within the Viewstate to protect against spoofed post backs. Add the following in the OnInit virtual method of the Page-derived class (This property must be set in the Page.Init event).
protected override OnInit(EventArgs e) {
base.OnInit(e);
if (User.Identity.IsAuthenticated)
ViewStateUserKey = Session.SessionID; }
The following keys the Viewstate to an individual using a unique value of your choice.
(Page.ViewStateUserKey)
This must be applied in Page_Init because the key has to be provided to ASP.NET before Viewstate is loaded. This option has been available since ASP.NET 1.1
I have tried to put the above one in Base page, where all pages are deriving from that page But I am getting error like OnInit must return value
this is my code
public class BasePage : System.Web.UI.Page
{
protected override OnInit(EventArgs e) {
base.OnInit(e);
if (User.Identity.IsAuthenticated)
ViewStateUserKey = Session.SessionID; }
}
Many thanks in advance
The OnInit declaration is missing the return type void.
protected override void OnInit(EventArgs e)
Is there an equivalent for MVC.NET's OnActionExecuting in standard asp.NET? ?
I thought it would be Page_Load since OnActionExecuting would be called each time an action is executed (or the page loads). But I'm running into inheritance issues when I try to use Page_Load instead.
Since it is very difficult to make my solution work with a Page_Load I'm thinking I might not have the best ... solution.
Any thoughts on whether they are equivalent or close enough?
Background:
I'm converting a piece of an MVC3 application into a standard .NET to wrap in a SharePoint Web Part.
Here's the MVC code I'm trying to translate, as you can see its the user security bits I'm translating:
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
if (!SiteCacheProvider.ItemCached(enmCacheKey.SiteSetting)) {
if (filterContext.IsImplementedGeneralPrincipal()) {
IUserProfile userProfile = ((IGeneralPrincipal)filterContext.HttpContext.User).UserProfile;
SiteCacheProvider.ChangeSiteSetting(userProfile.SiteID);
}
}
base.OnActionExecuting(filterContext);
}
First, take on account that no Actions are in ASP.NET because the model is different (Event-Based) - There're no methods(actions) which you can decorate with Action Filters, it's all about the Page-Cycle events.
Second, In ASP.NET, you may use HTTP modules (HttpApplication.BeginRequest particularly) in order to intercept incoming requests to your application pages by adding your required logic.
From MSDN:
HTTP Modules use to intercept HTTP requests for modifying or utilize
HTTP based requests according to needs like authentication,
authorization, session/state management, logging, modifying Response,
URL rewriting, Error handling, Caching....
For example:
using System;
using System.Web;
using System.Collections;
public class HelloWorldModule : IHttpModule
{
public string ModuleName
{
get { return "HelloWorldModule"; }
}
public void Init(HttpApplication application)
{
application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
application.EndRequest += (new EventHandler(this.Application_EndRequest));
}
private void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("<h1>HelloWorldModule: Beginning of Request</h1><hr>");
}
private void Application_EndRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("<hr><h1>HelloWorldModule: End of Request</h1>");
}
public void Dispose()
{
}
}
In my project (c#), we have an HttpModule that creates a custom Principal that we attach to the CurrentPrincipal.
This is working in all of our MVC3 apps and in our classic ASP.Net apps.
We have an AuthorizeAttribute override we use to secure our Controller methods - seems pretty standard.
The problem is that in the custom authorizeAttribute, the user (httpContext.User) is a RolePrincipal and not the custom principal.
To troubleshoot, I put some handlers in my global.asax to trap beginrequest() and endrequest(). Well, in BeginRequest my User is what we expect - the custom principal. In EndRequest, the user is a RolePrincipal again. The web.config declarations of the HttpModule are good - I can step thru the HttpModule's code.
Does anyone know what's going on? We have a custom HttpModule, but I can't modify that code for this project (it's being used everywhere and it works fine).
This is my first MVC4 project - I'm wondering if MVC4 does something differently.
Code below. Is there any info I've left out?
edit: added authorizationattribute code.
Code
(In HttpModule)
private void BeginRequest(object Sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
var Id = new TASBIdentity();
context.User = new TASBPrincipal(Id);
Thread.CurrentPrincipal = context.User;
(etc...)
(In global.asax)
void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
var user = context.User; // user is correct type
}
void Application_EndRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
var user = context.User; // user is default type (not correct)
}
(In the authorizeattribute)
public class SecuredByFunctionAttribute : AuthorizeAttribute
{
private readonly string _functionKey;
public SecuredByFunctionAttribute(string functionKey)
{
_functionKey = functionKey;
}
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
{
return httpContext.User.IsInRole(_functionKey);
}