Determine if user can access the requested page? - asp.net

I have an ASP.Net website with multiple roles, each with access to a separate directory (i.e. admin users can access /admin, shoppers can access /shop etc), using a shared login page. If someone visits the login page with the return URL set to a directory they do not have access to (e.g. a shopper visits /login.aspx?returnurl=/admin/index.aspx), the user can authentice successfully (the login credentials are valid), but they end up back at the login page (they don't have access to the page they've requested).
How do I pick this up, so I can display a message do the user?

UrlAuthorizationModule.CheckUrlAccessForPrincipal()
is what you need to use to test user access to a location (page or folder) ( http://msdn.microsoft.com/en-us/library/system.web.security.urlauthorizationmodule.checkurlaccessforprincipal.aspx )

I ended up doing this in the page_load event of the login page:
if (User.Identity.IsAuthenticated)
{
LoginErrorDetails.Text = "You are not authorized to view the requested page";
}
The thinking being, if an authenticated user ends up at the login page, they have either been sent their as a result of trying to access an page they are not authorized to view, or they have authenticated and then manually gone to the log in page (unlikely).
A further action would be to send the user to the relevant home page whenever they visit the login page, if they are already authenticated.

One approach would be to override OnLoad of your aspx forms and check if the authenticated user is allowed access to the resource based on the role. So you create a BasePage.cs (in which you define a class BasePage which inherits from System.Web.UI.Page) for example from which all your Forms (aspx) inherit, in which you do this:
protected override void OnLoad(EventArgs e)
{
InitializeSitemap();
if (SiteMap.CurrentNode != null)
{
if (!UrlHelper.IsAnonymousAllowed(SiteMap.CurrentNode) && (!HttpContext.Current.User.Identity.IsAuthenticated || !UrlHelper.IsAccesible(SiteMap.CurrentNode)))
{
// You can redirect here to some form that has a custom message
Response.Redirect("~/Forms/Logout.aspx");
return;
}
}
base.OnLoad(e);
}
Then in your UrlHelper class you need that IsAccessible function used above:
public static bool IsAccesible(SiteMapNode node)
{
bool toRole = false;
foreach (string role in node.Roles)
{
if (role == "*" || HttpContext.Current.User.IsInRole(role))
{
toRole = true;
}
}
return toRole;
}
Here is IsAnonymousAllowed in case you wondered:
public static bool IsAnonymousAllowed(SiteMapNode node)
{
return node[AllowAnonymousAttribute] != null ? bool.Parse(node[AllowAnonymousAttribute]) : false;
}

If you have different directories and you are using asp.net authentication it is very easy.
All you need is to put web.config file in each directory and define roles which can access files in that directory like this:
<authorization>
<allow roles="shoppers"/>
<deny users="?"/>
</authorization>
You can get more details from this article on MSDN
You can set all in main web.config like this:
<!-- Configuration for the "sub1" subdirectory. -->
<location path="sub1">
<system.web>
<httpHandlers>
<add verb="*" path="sub1" type="Type1"/>
<add verb="*" path="sub1" type="Type2"/>
</httpHandlers>
</system.web>
</location>
<!-- Configuration for the "sub1/sub2" subdirectory. -->
<location path="sub1/sub2">
<system.web>
<httpHandlers>
<add verb="*" path="sub1/sub2" type="Type3"/>
<add verb="*" path="sub1/sub2" type="Type4"/>
</httpHandlers>
</system.web>
</location>
</configuration>
This is from this article on MSDN :)
EDIT:
In your page load method do this:
if(!User.IsInRole("shopper"))
{
lblNoAccess.Visible=true;
lnkHome.Url="PATH_TO_HOME_PAGE_OF_THIS_ROLS";
}
Hope this helps you!

You can redirect him on the index page, telling him that he cannot access that page;)

Well, why don't you catch the directory in the login page? If the login page can determine which directory the user is trying to access, maybe they can get redirect to the right page based on role. If someone tries to go to /admin, and authentication succeeds, you can check if they do have access there. If not, you can either redirect to basic landing page indicating they do not have access or you redirect them to the role's landing page.
EDIT:
You could probably do the redirecting in the LoggedIn event of the control.

One other option is to set a session variable when you're checking rights, and displaying that on the login page.
So you could do:
if(!User.IsInRole("shopper"))
{
session("denied") = "You don't have access to shop";
response.redirect("/login");
}
Then in the login page:
if ( session("denied") != "" ) {
message.text = session("denied");
session("denied") = "";
}

Related

How to hide "log out"-button when using the"FormsAuthentication"-method to log in?

I have a "log out"-button in a masterpage that I want hidden when the user is logged in.
The login-functionality is very simple and is implemented by the following code in the Web.config-file (as well as some simple code in a log-in page):
<authentication mode="Forms">
<forms name="KunstCookie"
loginUrl="InnUtlogging.aspx"
defaultUrl="SalgsOversiktAdmin.aspx"
protection="All"
timeout="30" path="/" />
</authentication>
I manage to log in and out using a user name and password I set up on a log-in page.
I am trying to hide the log-out button while I am logged in by including the following code in the masterPage.master.cs file:
protected void Page_Load(object sender, EventArgs e)
{
if (Session["kunstCookie"] != null)
{
ButtonLogout.Visible = false;
}
}
But the button is still there when I am logged in. There is no error message when I load the page. Its almost like the cookie file doesn't exist or something.
Appreciate any help.
Found out how to do this. Instead of:
if (Session["kunstCookie"] != null)
I inserted:
if (!HttpContext.Current.User.Identity.IsAuthenticated)
I found the answer here:
Login and Logout in master page

Implement RedirectFromLoginPage with two defaultUrl in asp.net

I am Working on asp.net with two Login page for Staff and Student.When the Login is successful the user will be taken to WELCOME Page.But the problem is I have used RedirectFromLoginPage if the authentication is successful.Here is the code for that.
protected void Buttontbl1_Click(object sender, EventArgs e)
{
if (AuthenticateUser(Textusertbl1.Text,textpastbl1.Text))
{
FormsAuthentication.RedirectFromLoginPage(Textusertbl1.Text, CheckBoxtbl1.Checked);
}
else
{
errorlbl.Text="Invalid Username or Password";
}
}
I have given the defaultUrl as WelcomeStaff.aspx so if the authentication is successful the user is redirected to that.This is the code in Web.config file
<authentication mode="Forms">
<forms loginUrl="SelectUser.aspx" defaultUrl="welcomeStaff.aspx"/>
</authentication>
<authorization>
<deny users="?"/>
</authorization>
So,I need the following to be implemented,
I want the same for another login.
-If the authentication is successful the user must be redirected to DefaultUrl="WelcomeStudent.aspx"
Its working fine for One Login Page.But I don't know how to implement for two aspx pages
So,Can we have two defaultUrl for two aspx file? Is there any other way to implement?Iam new to asp.net.Plz help.Thanks in advance
The way I usually deal with that kind of situation is configure that app to return to a redirect page (ex : redirection.aspx) that will check if the user is authenticated and if so, will redirect the user to another page based on is role. ex :
if (User.Identity.IsAuthenticated)
{
if(User.IsInRole("Student"))
{
Response.Redirect("WelcomeStudent.aspx");
return;
}
else if(User.IsInRole("Staff")
{
Response.Redirect("welcomeStaff.aspx");
return;
}
}
//For any other situation, return to login
FormsAuthentication.RedirectToLoginPage();
I hope this will help you.

Redirect from page1 to page2, two questions

I have a my-site.ru/page1.apsx which will be a part of my-site.ru/page2.aspx so I need to rewrite (or redirect ?) page1.aspx to page2.aspx
I added this to my web.config:
<system.web>
<urlMappings enabled="true">
<add url="~/page1.aspx" mappedUrl="~/page2.aspx"/>
</urlMappings>
</system.web>
The only thing I don't know hot to fix is: why text in address bar is my-site.ru/page1.aspx but i see my-site.ru/page2.aspx ?? I want while redirecting (rewriting) text in address bar changes too.
Question2: How will it reflect on SEO of page1.aspx ? If possible, please, provide a link. i'm a SEO beginner.
PS: I'm not a native english speaker so there must be some errors.
if you are not going to need the content reflected on page1.aspx or if you are going to move the content to your page2.aspx, I would suggest you to do a 301 redirect, which is a a permanent redirect this will affect your seo passing all the SEO information to the page you´re doing the redirect which is page2.aspx in this case.
from the seo perspective other things you can do are:
- remove page1 from your xml sitemap (if you have any)
- Exclude the page from robots.txt
to perform a redirect either you can do it in IIS 7 (or above) you can include an element in your web.config like:
<httpRedirect enabled="true" exactDestination="true" httpResponseStatus="Permanent">
<add wildcard="/page1.aspx" destination="/page2.aspx" />
</httpRedirect>
or you can code the redirection and check for the url in each request like:
public class RedirectHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(this.context_BeginRequest);
}
private void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
//check here context.Request for using request object
if(context.Request.FilePath.Contains("page1.aspx"))
{
context.Response.RedirectPermanent("/page2.aspx");
}
}
}
if you are using .NET 4.0 or above take a look to the permament redirection
just be aware that if you perform a regular response.redirect you are doing a 302 redirect that will affect your seo.
on page load
Write this
server.transfer("Page2.aspx")

Web Forms Authentication from code-behind

Within my application a privileged user can add/delete/update user roles (while also assigning them to specific users). The below excerpt shows a rule in my web.config file which allows the functionality of user blocking to only administrators:
<location path="block-user.aspx">
<system.web>
<authorization>
<allow users="Administrator"/>
</authorization>
</system.web>
</location>
What if I want to dynamically add or delete other roles besides the default one? Can this be done through code-behind?
If you want to restrict some pages to certain roles, you can do this in Page_Load function;
protected void Page_Load(object sender, EventArgs e)
{
if(!User.IsInRole(allowedrole))
{
Response.Redirect("block-user.aspx");
}
else
{
//do stuff
}
}

ASP.Net - How can I allow imported script files be viewed by unauthenticated users when using Forms Authentication?

I'm using ASP.Net and forms authentication. When a user is directed to the Login Page I get a JavaScript error:
Message: Syntax error Line: 3 Char: 1
Code: 0 URI:
http://localhost:49791/login.aspx?ReturnUrl=%2fWebImageButton.js
This is because I am using a Custom Image Button in a separate Web Control Project control that adds a ScriptReference to the page:
public class WebImageButton : LinkButton, IScriptControl, IButtonControl
{
protected override void OnPreRender(EventArgs e)
{
// Link the script up with the script manager
ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);
if (scriptManager != null)
{
scriptManager.RegisterScriptControl(this);
scriptManager.Scripts.Add(new ScriptReference("<snip>.WebImageButton.js", "<snip>"));
}
base.OnPreRender(e);
}
}
If I add the following rule into my Web.Config, then the file is successfully imported:
<location path="WebImageButton.js">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
This isn't very good as I have a number of custom controls that do the same thing, and I don't particularly fancy authenticating each of their js files individually.
Is there no way that I can declare that all imported script references should be allowed? I tried authorising the WebResource.axd file in-case that allows it, but the page itself (when rendered) physically references the WebImageButton.js file.
The ideal scenario would be something like the following:
<location path="My.WebControlLibraryProject.Controls">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
Is there any way to achieve this without listing each file?
EDIT: Just to be clear, these script files are in another project and are not in my actual web project. I know how to declare the location paths of directory paths to include a large number of files in one wack, but I can't figure out how to authenticate automatic script references, which are from embedded resources.
Is the WebImageButton.js an embedded resource? As I've seen, you had implemented IScriptControl. Thus, you must return all of script references on the IScriptControl.GetScriptReferences. I think an embedded resource never be authorized. I use some of custom controls in different situation and don't have any problem. I'm wondering that script manager references to WebImageButton.js directly, and not in form of .axd file. So, I think the problem is arising from your resource file.
public class WebImageButton : LinkButton, IScriptControl, IButtonControl
{
protected ScriptManager ScriptManager
{
get
{
ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);
if (scriptManager == null)
{
throw new System.Web.HttpException("<snip>");
}
return scriptManager;
}
}
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
this.ScriptManager.RegisterScriptControl<WebImageButton>(this);
}
#region IScriptControl Members
public System.Collections.Generic.IEnumerable<ScriptDescriptor> GetScriptDescriptors()
{
yield break;
}
public System.Collections.Generic.IEnumerable<ScriptReference> GetScriptReferences()
{
yield return new ScriptReference("<snip>.WebImageButton.js", "Assembly Name");
}
#endregion
}
This is just a guess - have you tried putting in a wildcard in the location path? Perhaps something like < location path="*.js">?
You can specify a generic location and put all your scripts there so that all the scripts that don't require authorization will pass. You just need to change the path to whatever folder you want it to be and put the scripts there.
That will work for not only scripts, but other resources as well, such as images, style sheets, etc.

Resources