I have a class MainController and I have applied Authorize attribute to Index method but its not re-directed it to the LogOn page.
[Authorize]
public ActionResult Index()
{
MyBusinessObject obj = new MyBusinessObject(1);
return View(obj );
}
I have following added to web.config
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication
Any ideas what I may be missing?
Related
I'm trying to implement custom error handling within a Web API project using my web.config file. My issue is that the redirect is not happening. I have the following set up in my web config:
<customErrors mode="On" defaultRedirect="~/Page/Error?errorId=59">
<error statusCode="403" redirect="~/Page/Error?errorId=59"/>
</customErrors>
This is where it may be tricky:
I'm using a custom attribute that I'm placing in my controller, and the attribute returns a 403 status code if the request is not coming from a listed referrer.
Here's the attribute Code:
public class Action1DebugActionWebApiFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
// pre-processing
HttpRequestMessage request = actionContext.Request;
string ipAddress = ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
if (!IsIpAddressAllowed(ipAddress.Trim()))
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden);
}
}
Then I add the attribute to my controller like so:
[Action1DebugActionWebApiFilter]
[HttpGet]
[Route("MyRedirect")]
public IHttpActionResult MyRedirect([FromUri]UserModel myUser)
I know the 403 is getting produced because I can see it in my Firefox network tab. But the redirect isn't happening (verified in Fiddler). I just get a blank screen on the controller redirect with all the Get parameters just sitting there.
Any ideas?
That is because the <customErrors> section does not apply to asp web api.
I use custom membership for Users and Roles in my MVC3 application. I have custom user/roles class. And I have the extended the RoleProvider and MembershipProvider classes for this.
I seem to have a case of roles going missing sometimes in my application and my Authorize [Roles='xyz'] attribute not working correctly and trying to redirect to Account/LogOn. When my user logs into the application, all I do is
if (ModelState.IsValid)
{
if (MyCustomSecurity.Login(model.UserName, model.Password, model.RememberMe))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
--other stuff
}
MyCustomSecurity.Login method basically looks up the user in the database and if valid sends a true value back.
When trying to debug the issue with my application, I came across the links below
http://www.codeproject.com/Articles/578374/AplusBeginner-27splusTutorialplusonplusCustomplusF
ASP.NET MVC Forms Authentication + Authorize Attribute + Simple Roles
Should I also be overriding FormsAuthentication_OnAuthenticate() as mentioned in this link? Or does the RoleProvider extended class take care of this?
Thank You
If you use roles in AuthorizeAttribute, and roles are your own classes, so you need to override RoleProvider, especially method GetRolesForUser:
public class CustomRoleProvider : RoleProvider
{
public override string[] GetRolesForUser(string username)
{
// put your logic to discover which roles the user has
}
}
After doing that, you have to register you CustomRoleProvider in Web.Config:
<roleManager enabled="true" defaultProvider="CustomRoleProvider">
<providers>
<clear/>
<add name="CustomRoleProvider" type="%YOURNAMESPACE%.CustomRoleProvider" />
</providers>
</roleManager>
I am beginner with mvc3 and i and i have created an internet application for which i need to apply windows authentication and check for the user roles in the AD. Is that possible with LDAP? I have searched online but nothing seems clear. Hence, request you guys to assist or post some links which have clear explanation of the procedure to be followed.
Thanks in advance!
It is possible,
Have a look at this URL
Yes it is possible. There are many samples of this online.
In your web.config add the LDAP connection string:
<connectionStrings>
<add name="ADConnectionString" connectionString="LDAP://what ever it is" />
</connectionStrings>
Also add the following:
<authentication mode="Forms">
<forms name=".ADAuthCookie" loginUrl="~/Account/LogOn" timeout="15" slidingExpiration="false" protection="All" />
</authentication>
<membership defaultProvider="ADMembershipProvider">
<providers>
<clear />
<add name="ADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider" connectionStringName="ADConnectionString" attributeMapUsername="sAMAccountName" />
</providers>
</membership>
The rest should work the same as normal SQL membership:
public ActionResult LogOn()
{
return View();
}
[HttpPost]
public ActionResult LogOn(LogOnViewModel viewModel, string returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(viewModel.UserName, viewModel.Password))
{
}
}
}
Your LogOnViewModel:
public class LogOnViewModel
{
public string UserName { get; set; }
public string Password { get; set; }
}
I hope this can help you in the right direction.
I am trying to implement a very basic login scheme for my MVC3 site. If I understand correctly, instead of adding the [Authorize] markup to each of my controller classes, I should be able to simply implement a global setting. To accomplish this, I have added the following into global.asax:
protected void Application_Start()
{
RegisterGlobalFilters(GlobalFilters.Filters);
}
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new AuthorizeAttribute());
}
and in my webconfig, I added:
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
The result is that the resulting page is totally blank. Looking at the url, it seems that mvc is redirecting to my login route as expected except the page empty. If I comment out the code in global.asax and just place the [Authorize] markup directly in each contoller, it works as expected.
As a workaround, I have implemented what I have read the MVC2 best practice to be, which was to create a BaseController:Controller class, add the [Authorize] markup to it, and then change the inherentences of all of my controllers to inheret from BaseController instead of Controller.
That seems to work well enough for now.
But why isn't the global.asax implementation working?
Let's see what's happening here:
You are navigating to /
Your global authorize attribute kicks in and since the user is not authenticated he is redirected to ~/Account/LogOn (as instructed in your web.config file) for authentication
Your global authorize attribute kicks in and since the user is not authenticated he is redirected to ~/Account/LogOn (as instructed in your web.config file) for authentication
Same as 3.
Same as 4.
...
I think you get the point. The LogOn action should be excluded from authentication otherwise the user can never get a chance to login to your web site.
Since you have applied the Authorize attribute globally this cannot be done. One possible way is to write a custom AuthorizeAttribute that will be applied globally and which will exclude this action from authentication.
So you could write a marker attribute:
public class AllowAnonymousAttribute : Attribute
{
}
and a global custom authorize attribute:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
var exclude = ((AllowAnonymousAttribute[])filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), false)).Any();
if (!exclude)
{
base.OnAuthorization(filterContext);
}
}
}
that will be registered:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new MyAuthorizeAttribute());
}
Now all that's left for you is to decorate the controller actions that you want to be excluded from authentication with our marker attribute:
public class AccountController : Controller
{
[AllowAnonymous]
public ActionResult LogOn()
{
return View();
}
[AllowAnonymous]
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
...
}
}
I'm trying to use a custom role provider in an MVC3 app. I've already got the membership provider working ok using Ninject but can't seem to get the role provider working. The Membership provider doesn't require a parameterless constructor but role provider does. Here's some code snippets:
Web.config
<membership>
<providers>
<clear/>
<add name="MyMembershipProvider" type="MyApp.Models.NHibernateMembershipProvider"
applicationName="myApp" />
</providers>
</membership>
<roleManager enabled="true">
<providers>
<add name="MyRolesProvider" type="MyApp.Models.NHibernateRoleProvider"
applicationName="myApp" />
</providers>
</roleManager>
I have a Ninject module.
public class MyNinjectModule : NinjectModule
{
public override void Load()
{
this.Bind<ISession>().ToMethod(
x => MyApp.MvcApplication.SessionFactoryData.GetCurrentSession());
// Respository
this.Bind<IUserRepository>().To<UserRepository>();
this.Bind<MembershipProvider>().To<NHibernateMembershipProvider>();
this.Bind<RoleProvider>().To<NHibernateRoleProvider>();
}
}
The custom Membership provider
public class NHibernateMembershipProvider : MembershipProvider
{
private IUserRepository _repo;
public NHibernateMembershipProvider(IUserRepository repository)
{
_repo = repository;
}
...
The role provider
public class NHibernateRoleProvider : RoleProvider
{
private IUserRepository _repo;
public NHibernateRoleProvider(IUserRepository repository)
{
_repo = repository;
}
...
I then configure my controller to require an authorize
[Authorize(Roles="Admin")]
public ActionResult Edit(int? id)
{
...
I get this error when starting the app.
Parser Error Message: No parameterless constructor defined for this object.
Source Error:
Line 49: <roleManager enabled="true">
Line 50: <providers>
Line 51: <add name="MyRolesProvider" type="MyApp.Models.NHibernateRoleProvider"
Line 52: applicationName="myApp" />
Line 53: </providers>
I can access the users through the membership provider, so the repository is being injected ok, but the roles provider seems to be different. Why does the role provider require a constructor-less parameter? Is there a simple way to get the role provider to work with Ninject. Any help appreciated.
Since the role provider, in this case the NHibernateRoleProvider is instantiated by the ASP.NET framework the best solution is to use the service locator pattern. The service locator pattern is normally considered to be an anti-pattern but sometimes you have to be pragmatic and accepted the limitation on the framework that is being used (in this case the ASP.NET framework).
Assuming you are using an implementation of the IDependencyResolver interface for Ninject. The following code should work.
public class NHibernateMembershipProvider : MembershipProvider
{
private IUserRepository _repo;
public NHibernateMembershipProvider()
{
_repo = DependencyResolver.Current.GetService<IUserRepository>();
}
// ...
}
Alternatively, if you're using the Ninject.Web.Mvc nuget package you can always use property injection on your role provider as illustrated here:
ASP.NET MVC 3 Ninject Custom Membership and Role Provider