ASP.NET MVC – HTTP身份validation提示

是否有可能使我的应用程序要求提供用户名和密码之前渲染视图? 就像在Twitter API获取有关您的帐户的信息:

http://twitter.com/account/verify_credentials.xml

所以在渲染视图||之前 文件它要求你插入你的用户名和密码,我认为这是直接在服务器上,因为curl请求是基于用户名:密码以及如下所示:

curl -u user:password http://twitter.com/account/verify_credentials.xml 

正如我试图build立一个API遵循相同的结构,我想知道如何在ASP.NET MVC C#上做到这一点。 我已经在ruby on rails上使用它,它非常简单,如:

 before_filter :authenticate def authenticate authenticate_or_request_with_http_basic do |username, password| username == "foo" && password == "bar" end 

我不认为[Authorize]filter是相同的,因为我相信这只是一个redirect,它会将您redirect到基于帐户数据库的Accounts Internal Controller,在这种情况下,我将使用另一个数据库, web服务,并提交信息后进行validation。 但是,我需要采取行动来要求用户,并根据请求传递凭据。

提前致谢


更新:

其实要请求一个页面,需要这个authentication(即Twitter),我将不得不根据其要求宣布这一点

 request.Credentials = new NetworkCredential("username", "password"); 

这将反映提示的用户名和密码。

所以,从另一方面来说,这是完全一样的,如果可以根据请求向authentication提示信息提供信息,那么我怎么会要求这个authentication呢?

所以每次有人试图向我的应用程序请求例如:

HTTP://为MyApplication /客户/ verify_credentials

它应该要求一个用户名和密码与该服务器提示,以检索curl的信息,例如它会是这样的

 curl -u user:password http://myapplication/clients/verify_credentials 

那么,要求基本authentication,你需要返回401状态码。 但是这样做会导致当前的身份validation模块执行其默认的未授权处理程序(对于表单身份validation,这意味着redirect到login页面)。

我写了一个ActionFilterAttribte来查看当web.config没有安装validation模块时是否可以获得所需的行为。

 public class RequireBasicAuthentication : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var req = filterContext.HttpContext.Request; if (String.IsNullOrEmpty(req.Headers["Authorization"])) { var res = filterContext.HttpContext.Response; res.StatusCode = 401; res.AddHeader("WWW-Authenticate", "Basic realm=\"Twitter\""); res.End(); } } } 

和控制器的行动:

 [RequireBasicAuthentication] public ActionResult Index() { var cred = System.Text.ASCIIEncoding.ASCII .GetString(Convert.FromBase64String( Request.Headers["Authorization"].Substring(6))) .Split(':'); var user = new { Name = cred[0], Pass = cred[1] }; return Content(String.Format("user:{0}, password:{1}", user.Name, user.Pass)); } 

该操作成功打印了我input的用户名和密码。 但我真的怀疑这是做到这一点的最好方法。 除了以这种方式询问用户名和密码之外,你别无select吗?

你真的想创build一个服务,而不是一个Web应用程序,根据我读过的。 我在这里猜测,但我认为你selectASP.NET MVC利用路由和按照你想要的方式构buildURL? 纠正我,如果我错了。

在我看来,解决您遇到的问题的最好方法是使用WCF构buildRESTful Web服务,如果您要返回数据。 这篇文章应该帮助你开始如果你想走这条路线。

否则,您将需要进一步处理请求并进行身份validation。 如果是这样,我可以帮助提供更多的信息和代码。

我修改了çağdaş答案把我的自定义ActionFilter属性中的整个逻辑。

 public class BasicAuthenticationAttribute : ActionFilterAttribute { public string BasicRealm { get; set; } protected string Username { get; set; } protected string Password { get; set; } public BasicAuthenticationAttribute(string username, string password) { this.Username = username; this.Password = password; } public override void OnActionExecuting(ActionExecutingContext filterContext) { var req = filterContext.HttpContext.Request; var auth = req.Headers["Authorization"]; if (!String.IsNullOrEmpty(auth)) { var cred = System.Text.ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(auth.Substring(6))).Split(':'); var user = new { Name = cred[0], Pass = cred[1] }; if (user.Name == Username && user.Pass == Password) return; } var res = filterContext.HttpContext.Response; res.StatusCode = 401; res.AddHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Ryadel")); res.End(); } } 

它可以用来在基本authentication下整个控制器:

 [BasicAuthenticationAttribute("your-username", "your-password", BasicRealm = "your-realm")] public class HomeController : BaseController { ... } 

或特定的ActionResult:

 public class HomeController : BaseController { [BasicAuthenticationAttribute("your-username", "your-password", BasicRealm = "your-realm")] public ActionResult Index() { ... } } 

注意 :上面的实现需要开发人员手动插入用户名和密码作为ActionFilter所需的参数,但可以很容易地进行扩展,使其支持任何授权机制(MembershipProvider,ASP.NET Identity,外部DBMS或文件上的自定义用户库等)。 )通过删除自定义构造函数并相应地修改OnActionExecuting方法IF块。

你也可以在这里阅读更多的信息

这是为我工作的方式。 这是一个小脚步工作,但它会使IIS和MVC3更像所有其他基本Http身份validation系统,如Apache …

步骤1。

确保为IIS安装了“基本身份validation”。

(例如:控制面板 – >程序和function – >打开或closuresWindowsfunction)

*我目前正在使用Windows 7,但不确定确切的path。 [GOOGLE:在IIS中安装基本身份validation]应该让你closures。

第2步。

确保在您的网站下启用了基本身份validation。 如果必须在上一步中安装,则需要确保重置IIS服务,并确保所有应用程序池都已closures。

第3步。

(注:我正在使用MVC3,觉得这应该适用于大多数模型,包括ASP.Net,没有太多的大惊小怪。)
在您的项目中,您将需要添加以下类:

 public class ServicePrincipal : IPrincipal { // This answers the "What am I allowed to do" question // In real life, this guy will contain all your user info // and you can put what ever you like and retrieve it // later via the HttpContext, on your application side. // Some fun with casting will be required. public static IPrincipal Default { get { return new ServicePrincipal { Identity = new ServiceIdentity { AuthenticationType = "Test", IsAuthenticated = true, Name = "Basic" } }; } } public IIdentity Identity { get; set; } public bool IsInRole(string role) { // If you want to use role based authorization // eg [Authorize(Roles = "CoolPeople")] // This is the place to do it and you can do // anything from load info from a db or flat file // or simple case statement...though that would // be silly. return true; } } public class ServiceIdentity : IIdentity { // This answers the "Who Am I" Question public string AuthenticationType { get; set; } public bool IsAuthenticated { get; set; } public string Name { get; set; } } public class ServiceModule : IHttpModule { // This is the module for IIS public void Init(HttpApplication context) { context.AuthenticateRequest += this.BasicAuthenticationRequest; } public void BasicAuthenticationRequest(object sender, EventArgs e) { HttpApplication app = sender as HttpApplication; if( !ServiceProvider.Authenticate(app.Context) ) { // Total FAIL! } } public void Dispose() { // Clean up the mess, if needed. } } public class ServiceProvider { public static bool Authenticate( HttpContext context ) { // For the example we are going to create a nothing user // say he is awesome, pass him along through and be done. // The heavy lifting of the auth process will go here // in the real world. HttpContext.Current.User = ServicePrincipal.Default; return true; } } 

步骤3a。 [编辑]

以下是您将使用的不同库

 using System.Security.Principal; using System.Web; 

只是想把这些扔进去。当人们把它们抛出去的时候,我讨厌它。 🙂

步骤4。

将以下内容添加到您的networkingconfiguration中。 请注意,我包括周围的结构,例如“configuration”标签…这只是一个路线图,如果你已经有一个“configuration”标签不添加另一个或IIS让你不高兴。

 <configuration> <system.webServer> <modules runAllManagedModulesForAllRequests="true"> <add name="ServiceCredentialModule" type="{Namespace}.ServiceModule"/> </modules> </system.webServer> <configuration> 

请注意,{Namespace} .ServiceModule中的命名空间是您将步骤3中的类放入的命名空间。

…这就是它。