Invoke an action that is using ASP.NET MVC [Authorize] from outside the application
Is this possible?
I'd like to expose a URL (action) such as http://mysever/myapp/UpdateHeartbeat/.
In my MVC application it looks like
[Authorize]
[AcceptsVerbs(HttpVerbs.Post)]
public ActionResult UpdateHeartbeat()
{
// update date in DB to DateTime.Now
}
Now, in my MVC application the user has logged in via FORMS authentication and they can execute that action to their hearts content.
What I want to do, is hit that URL from a Console application and be able to authenticate (as part of an API that I wouldl like to build) -- is开发者_如何学C there a way I can do that without removing the [Authorize] attribute and adding username/password as parameters to the POST?
Sure this is possible. This is done in unit testing all the time. Personally, I use RhinoMocks along with MVCContrib.TestHelper to call my controller actions, both authenticated and not authenticated. Here is a sample piece of code that I use to test my controllers:
private MockRepository _mocks = new MockRepository();
public ControllerTestBase()
{
}
public static T GetController<T>()
{
return this.GetController<T>(null);
}
public T GetController<T>(BPUser authenticatedUser)
{
TestControllerBuilder testContBuilder = new TestControllerBuilder();
if (authenticatedUser != null)
{
var identity = _mocks.DynamicMock<IIdentity>();
SetupResult.For(identity.IsAuthenticated).Return(true);
SetupResult.For(identity.Name).Return(authenticatedUser.ID.ToString());
_mocks.Replay(identity);
var pAttrs = new System.Collections.Hashtable();
pAttrs["UserID"] = authenticatedUser.ID.ToString();
pAttrs["UserName"] = authenticatedUser.UserName;
testContBuilder.HttpContext.User = new UserPrinciple(identity, new string[] { }, pAttrs);
}
return testContBuilder.CreateController<T>();
}
There is a little custom stuff in there for my implementation of IPrinciple, but hopefully it's a start.
Edit - Example Usage Here's how you would use this:
var authenticatedUser = SomeCodeToGetMyUser();
var controller = ControllerTestBase.GetController<YourController>(authenticatedUser);
controller.UpdateHeartbeat();
The Authorize filter actually gets the IPrincipal for the user from the current context so this would not be possible. You will want an alternate form of auth for that method.
A quick google search provides a link to the following blog post that may be of use:
http://davidhayden.com/blog/dave/archive/2009/04/09/CustomAuthorizationASPNETMVCFrameworkAuthorizeAttribute.aspx
精彩评论