I'm new in mvc and i try to figured out something.
I have intranet application with login page. I put some stuff in Session and in masterpage on page init events i check
If Page.User.Identity.IsAuthenticated Then
If Session("someThing") Is Nothing Then Me.SetupSession()
End If
This is from web forms, and this is for all page.
How can I do same stuff in MVC 3.
you can use an Action filter to secure the action method on your controller
if you have a base controller just add the below attribute otherwise you need to add this attribute on all the controller you want to secure
[Authorize]
public class SomeController : DefaultController
{
public ActionResult SomeAction(){
}
}
this attribute allow you to specify a message as well
[Authorize(Message = "Access to the blah blah function requires login. Please login or create an account")]
for more info:
http://www.asp.net/mvc/tutorials/authenticating-users-with-forms-authentication-cs
Depending on where you need this, you may write a Global filter to set up the session, or do it in the controller's Initialize() method.
Related
In my DocType i have a property by the name of "membersOnly" (true/false).
When checked, I want to check, if the user is logged in, if not, redirect to login page with a referrer.
But what is the best way to do this - I dont want to have it in my Master template. How can I hook into the request pipeline, check if the "membersOnly" field excist, and if it does, and it is checked, and the user is not logged in, redirect the user?
Any short snippets out there?
Also, I am aware of the built-in Umbraco way of doing this. But for this case, i need it to be just a simple checkbox on the page in the backend - but the functionality that it fires, is basicly the same, as if i used the built-in Umbraco way in the backend.
You can do this using route hijacking then checking authentication through your controllers. However, if all you have to do is check for authentication, it might be a little bit of an overkill to do route hijacking for your doc types.
Essentially, to do route hijacking, you create a controller with the same name as your doctype, so if your doctype is "memberPage", your controller would look like this:
public class MemberPageController : RenderMvcController
{
public ActionResult Index(RenderModel model)
{
return base.Index(model);
}
}
Notice how it must inherit RenderMvcController in order to work.
Before returning the base RenderMvcController method "Index", you can now run code, e.g. to check authentication.
So you could do this:
public ActionResult Index(RenderModel model)
{
if (Members.IsLoggedIn())
{
return base.Index(model);
}
else
{
return Redirect("~/");
}
}
The cleanest way to implement this yourself, would probably be by creating a custom filter derived from AuthorizationFilterAttribute (located in System.Web.Http.Filters).
Having the derived object use the umbracocontext and query the settings based on the current page.
Umbraco does exactly the same for their custom validation, for some inspiration check out MemberAuthorizeAttribute at github
I learned I can redirect the user to a different page like this http://www.asp.net/web-forms/tutorials/security/membership/user-based-authorization-vb but I am wondering if there is a better way? Also, how can I just send an error message, instead of doing a redirect to a different view?
For instance, here is my code:
<Authorize(Roles:="Administrator")>
Public Class CompanyController
Could I add something like an error message to this if the user logs in but doesn't have the right credentials? Could I set an error in the ViewBag.Error? Thanks for your help.
The point of the Authorize attribute is to prevent access to the controller action if the user is not allowed. It doesn't execute the action at all and redirects to the LogOn action by default. The fact that the original action was not executed means that the view was not rendered.
If you don't want to get redirected to the LogOn action but create some custom view that will be rendered you could write a custom Authorize attribute and override the HandleUnauthorizedRequest method:
Public Class MyAuthorizeAttribute
Inherits AuthorizeAttribute
Protected Overrides Sub HandleUnauthorizedRequest(filterContext As AuthorizationContext)
Dim result = New ViewResult()
result.ViewName = "Forbidden"
result.ViewBag.ErrorMessage = "oops, you are not allowed"
filterContext.Result = result
End Sub
End Class
and then define the ~/Views/Shared/Forbidden.vbhtml view that will be rendered:
<h3>#ViewBag.ErrorMessage</h3>
and finally decorate your controller with this custom attribute:
<MyAuthorize(Roles:="Administrator")>
Public Class CompanyController
You can always create your own Authorization filter in MVC and do whatever you need it to.
You will need to create a class that implements IAuthorizationFilter.
You can have this authorization filter add stuff to ViewBag.Error instead of redirecting to another action if that's what you wanted to do. I'm not sure how useful that message will be if you don't provide a way for your user to authenticate, though.
I'm in the process of creating an Intranet site using Windows Authentication.
Maybe I'm not going about this the best way, but I'm trying to load partial views via calling a controller method that has an Authorize action filter wrapped around it, so that only authorized individuals are able to see that portion of the page. Say, for instance, I wanted to load administrator tools onto the page but only if the logged-in individual is an administrator.
So on the index.cshtml page I might have something like:
#Html.Action("LoadAdminTools","ControllerName")
The Controller would contain the code:
[Authorize(Roles="Admins")]
public ActionResult LoadAdminTools()
{
return PartialView("_AdminToolsPartialView");
}
And then the partial view containing the admin controls (or whatever) would render to the page - only if the logged-in user was part of the Admins role.
The 'problem' I'm having is that if the person logged-in is not authorized to load the partial view, the browser pops up the login dialog asking for the user's credentials. Closing the dialog without inputting any credentials causes the expected results - the partial view doesn't load while the rest of the page does. Cool, but annoying. Input the incorrect credentials and you get a 401 error - also as expected.
If it helps: In IIS, Anonymous Authentication is disabled, Windows Authentication is enabled.
"Automatic logon with current user name and password" is selected in Internet Options under "Security Settings - Local Intranet Zone."
My question is this: Is there a way to use the [Authorize] action filter to load a partial view (or to do anything, really) without the browser asking the user to log in? Just have it take the current logged-in credentials, check if they comply with the action filter, if they do, load the partial view, if not, then don't. If there isn't, is there simply a better way of going about what I want to accomplish here?
UPDATE
Beautiful. I read the solution to the question you posted, Mystere Man, created a new class inside the Controller's folder called IntranetAuthorizeAttribute.cs, threw in the code:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class IntranetAuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAuthenticated)
{
filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult(403);
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
Replaced the Authorize filter with my new IntranetAuthorize filter:
[IntranetAuthorize(Roles="Admins")]
public ActionResult LoadAdminTools()
{
return PartialView("_AdminToolsPartialView");
}
And now it loads the page just fine with no browser login dialog - with the partial view when it's an authorized user, and without the partial view when it is not an authorized user =)
Thank you!
Unfortunately, ASP.NET (and thus MVC) conflates Authorization and Authentication in may scenarios.
Check this question for a solution.
Why does AuthorizeAttribute redirect to the login page for authentication and authorization failures?
I just want to ensure they are logged in before running any code.
I found User.Identity.IsAuthenticated Which can be used for boolean to check login. But if I did redirect, it would still run code, plus I would have to put it everywhere?
In ROR there was a before_filter option we did, that checked at the top of each controller, and wouldnt run it otherwise.
Please can someone guide me on how to do this.
You can use AuthorizeAttribute for this:
When you mark an action method with AuthorizeAttribute, access to that
action method is restricted to users who are both authenticated and
authorized. If you mark a controller with the attribute, all action
methods in the controller are restricted.
The Authorize attribute lets you indicate that authorization is
restricted to predefined roles or to individual users. This gives you
a high degree of control over who is authorized to view any page on
the site.
If an unauthorized user tries to access a method that is marked with
the Authorize attribute, the MVC framework returns a 401 HTTP status
code. If the site is configured to use ASP.NET forms authentication,
the 401 status code causes the browser to redirect the user to the
login page.
For example:
[Authorize]
public ActionResult DoSomething()
{
// ...
}
At the top of your controller class, write this :-
[Authorize]
public class StoreManagerController : Controller
Use the Authorize Attribute.
[Authorize]
public ActionResult About()
{
return View();
}
I want to make the roles default for my controller class to "Administrators, Content Editors"
[Authorize(Roles = "Administrators, Content Editor")]
I've done this by adorning the controller with the attribute above. However, there is one action that I want to be available to all (namely "View"). How can I reset the Roles so that everyone (including completely unauthorized users) have access for this action.
Note: I know I could adorn every single action other action with the authorize attribute above but I don't want to have to do that all the time. I want all of the controllers actions to be unacessible by default so that if anyone adds an action they have to make a considered decision to make it available to the general public.
MVC4 has a new attribute exactly meant for this [AllowAnonymous]
[AllowAnonymous]
public ActionResult Register()
http://blogs.msdn.com/b/rickandy/archive/2012/03/23/securing-your-asp-net-mvc-4-app-and-the-new-allowanonymous-attribute.aspx
You can place the Authorize attribute on the action methods. Not just at the class level.
So, move the attribute from the controller class to just the action methods you want to secure.
The only solution I can think of so far is to create and register another controller so that I have one for anonymous access, and one for authorized access but that's not quite as elegant as I would have liked.