ASP.NETMVC5中的基本身份验证

lb3vh1jj  于 12个月前  发布在  .NET
关注(0)|答案(9)|浏览(90)

ASP.NET MVC 5中实现基本身份验证必须执行哪些步骤?
我读到OWIN不支持无cookie身份验证,那么基本身份验证通常是可能的吗?
我需要一个自定义属性吗?我不确定这些属性是如何工作的。

ymzxtsji

ymzxtsji1#

您可以使用自定义的过滤器过滤器属性来使用这个简单而有效的机制:

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();
    }
}

字符串
它可以用于将整个控制器置于基本身份验证之下:

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


或特定的搜索结果:

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


如果你需要更多的信息,请查看我写的关于这个主题的this blog post

lymnna71

lymnna712#

您可以使用自定义属性来实现这一点。在开源项目SimpleSecurity中有一个自定义属性的实现,它支持基本身份验证,您可以在这里下载。有一个参考应用程序来演示如何使用它。它最初是为了在MVC 4中使用SimpleMembership而开发的,最近已经成为ported to use ASP.NET Identity in MVC 5

50few1ms

50few1ms3#

我想修改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();
    }
}

字符串

kiz8lqtg

kiz8lqtg4#

@Darkseal给出了很好的答案。这是同样的代码,被重新用于ASP.NET Web API(MVC的近亲)。同样的想法,稍微不同的命名空间和上下文类。以完全相同的方式将其添加到类和方法中。

using System.Web.Http.Controllers;
using System.Web.Http.Filters;

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)
    {
        Username = username;
        Password = password;
    }

    public override void OnActionExecuting(HttpActionContext filterContext)
    {
        var req = filterContext.Request;
        var auth = req.Headers.Authorization;
        if (auth?.Scheme == "Basic")
        {
            var cred = Encoding.ASCII.GetString(Convert.FromBase64String(auth.Parameter)).Split(':');
            var user = new { Name = cred[0], Pass = cred[1] };
            if (user.Name == Username && user.Pass == Password) return;
        }
        filterContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
        filterContext.Response.Headers.Add("WWW-Authenticate", string.Format("Basic realm=\"{0}\"", BasicRealm ?? "YourRealmName"));
    }
}

字符串

qojgxg4l

qojgxg4l5#

HTTP基本身份验证不需要cookie。它基于HTTP请求中的HEADER。该头名为 Authorization,其值应该是用户名和密码组合成字符串“username:password”(所有base64编码)。
老实说,我从来没有在ASP.NETMVC中使用过基本的身份验证,但是我使用了Web API来创建一个自定义属性(对于Web API,可以从here开始,对于MVC,可以从这里开始)。

toe95027

toe950276#

你可以在Nuget(AuthPackage)上尝试这个包,它使你能够轻松地将身份验证添加到你的asp.net mvc中。
1.使用软件包管理器控制台安装软件包:
安装包AuthPackage
1.将连接字符串添加到您的Web.config中(appSettings):

<add key="connectionString" value="connectionStringHere" />

字符串
1.您已准备好注册用户、登录、注销
举例说明:

public async Task<ActionResult> SignIn()
    {
        var context = System.Web.HttpContext.Current;
        AuthUser authUser = new AuthUser(context);
        await authUser.SignIn("[email protected]", "123456");
        return RedirectToAction("Index", "Home");
    }


您可以阅读文档here

4sup72z8

4sup72z87#

Darkseal’s answer

[BasicAuthenticationAttribute("your-username", "your-password", 
    BasicRealm = "your-realm")]

字符串
有2个缺点:名称和密码是硬编码的,它们只支持单个用户。
更灵活的解决方案应该支持配置中存储的多个用户名/密码对。
Microsoft描述了一个示例https://gm/aspnet/samples/tree/main/samples/aspnet/WebApi/BasicAuthentication。

public abstract class BasicAuthenticationAttribute : Attribute, IAuthenticationFilter


在超载的

abstract Task<IPrincipal> AuthenticateAsync(string userName, string password,   
CancellationToken cancellationToken);


您可以执行检查以查找来自头的用户名/密码是否存在于用户名/密码对的配置/秘密列表中
https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/basic-authentication#basic-authentication-with-custom-membership It’s also possible to create HTTP module that performs Basic Authentication. You can easily plug in an ASP.NET membership provider by replacing the CheckPassword method.
OWIN实现示例https://github.com/scottbrady91/Blog-Example-Classes/tree/master/OwinBasicAuthentication/WebApi
在.Net核心中的可能实现在https://github.com/mihirdilip/aspnetcore-authentication-basic中描述

2admgd59

2admgd598#

我们的一个应用程序“意外地”使用了基本身份验证,因为Web.config中有以下代码:

<system.webServer>
    <modules>
        <remove name="FormsAuthentication" />
    </modules>
    ... other stuff
</system.webServer>

字符串
应用程序被配置为使用表单身份验证。每当使用普通表单身份验证时,浏览器身份验证窗口就会弹出。

kdfy810k

kdfy810k9#

这是一个接受的答案略有变化。我的情况是,我有一个n Asp.net(4.5.2)控制器,它既作为一个API,以及一个页面,只是返回说“你已经成功连接到服务器”。这样做的目的是,基本身份验证可以进行测试,以确保它是工作之前,尝试使用它与API。请注意,这是一个遗留应用程序和要求规定使用基本身份验证,这就是为什么它仍然需要。
问题是,网站的其余部分都是用FormsAuthentication设置的,所以当BasicAuthenticationFilter运行时,它会将结果从401未授权重定向更改为302重定向,用户最终会出现在登录页面上。
我真正想要的是在浏览器中显示Basic Auth弹出窗口。同样,这只是为了让最终用户可以测试凭据。这是我必须更改才能使其工作:

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"));
     filterContext.HttpContext.Response.StatusCode = 401;
     filterContext.HttpContext.Response.End();
}

字符串
请注意,使用这一行:

filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;


并没有真正抑制表单重定向(不知道为什么,似乎应该)。

[HttpGet]
  [BasicAuthentication("TestUserName", "Abc123*")]
  public ActionResult Submit()
  {
      return new ContentResult() { Content = "You have successfully connected to the AP&G GISB Server." };
  }


还要注意的是,实际的实现检查数据库中的用户名和密码,上面只是演示代码。

相关问题