ASP.NET MVC 5中的基本身份验证

Son*_*nic 41 asp.net authentication asp.net-mvc asp.net-mvc-5

ASP.NET MVC 5中实现基本身份验证必须执行哪些步骤?

我已经读过OWIN不支持无cookie身份验证,基本身份验证通常是否可行?

我需要自定义属性吗?我不确定这些属性是如何工作的.

Dar*_*eal 75

您可以使用自定义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;
        }
        filterContext.HttpContext.Response.AddHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Ryadel"));
        /// thanks to eismanpat for this line: http://www.ryadel.com/en/http-basic-authentication-asp-net-mvc-using-custom-actionfilter/#comment-2507605761
        filterContext.Result = new HttpUnauthorizedResult();
    }
}
Run Code Online (Sandbox Code Playgroud)

它可以用于在基本身份验证下放置一个完整的控制器:

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

或特定的ActionResult:

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

如果您需要其他信息,请查看我在该主题上撰写的博文.

  • 请注意,此属性不适用于Web API - 使用过滤器可能会更好 - http://weblog.west-wind.com/posts/2013/Apr/18/A-WebAPI-Basic -Authentication的授权,过滤器 (6认同)
  • 真棒.这正是我所需要的! (5认同)
  • 将此与表单身份验证相结合可能会导致问题:基本身份验证的401重定向到表单身份验证登录页面.为了避免这种情况,只需在行`filterContext.Result`之前添加行:`filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;`.您需要.NET 4.5或更高版本. (4认同)
  • @MacakM:发出质询的所有身份验证方案都需要域属性(不区分大小写).领域值(区分大小写)与正在访问的服务器的规范根URL相结合,定义了保护空间.这些领域允许将服务器上受保护的资源划分为一组保护空间,每个保护空间都有自己的身份验证方案和/或授权数据库.[来自RFC 1945(HTTP/1.0)和RFC 2617] (2认同)

Kev*_*ans 13

您可以使用自定义属性执行此操作.在开源项目SimpleSecurity中有一个支持基本身份验证的自定义属性的实现,您可以在此处下载.有一个参考应用程序来演示它是如何使用的.它最初是为与MVC 4中的SimpleMembership一起开发的,最近移植到MVC 5中使用ASP.NET Identity.


小智 8

我想修改Darkseal分享的答案,因为该代码存在一个重大的安全漏洞.如上所述,当调用res.End()时,该动作过滤器实际上不会终止请求.系统将提示用户输入凭据,如果凭据不匹配,则返回401响应,但仍在服务器端执行控制器操作.您需要将filterContext.Result属性设置为某个属性,以便请求正确终止,而不是继续执行操作方法.

这对我的情况特别糟糕,因为我试图保护从第三方接收数据馈送的Web服务端点.如上所述,此动作过滤器不保护任何内容,因为数据仍在通过我的操作方法推送.

我的"快速修复"如下:

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.AddHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Ryadel"));
        filterContext.Result = new HttpUnauthorizedResult();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • "快速修复"已经在@Darkseal的主要答案中应用了,```res.end()```的问题已被删除,取而代之的是````HttpUnauthorizedResult()``` (2认同)