答案 0 :(得分:70)
您可以使用自定义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();
}
}
它可用于在基本身份验证下放置一个完整的控制器:
[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()
{
...
}
}
如果您需要其他信息,请查看我就该主题撰写的this blog post。
答案 1 :(得分:13)
您可以使用自定义属性执行此操作。自定义属性的实现支持开源项目SimpleSecurity中的基本身份验证,您可以download here。有一个参考应用程序来演示它是如何使用的。它最初是为了与MVC 4中的SimpleMembership一起开发的,最近才开始ported to use ASP.NET Identity in MVC 5。
答案 2 :(得分:5)
我想修改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();
}
}
答案 3 :(得分:2)
HTTP基本身份验证不需要cookie。它基于HTTP请求中的HEADER。标题名为 Authorization ,其值应为用户名和密码,并将其组合成一个字符串“username:password”(所有base64编码)。
此致我从未使用ASP.NET MVC进行基本身份验证,但我使用Web API创建自定义属性(您可以从here开始使用WebAPI或here开始使用MVC)。
答案 4 :(得分:2)
来自@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"));
}
}
答案 5 :(得分:1)
您可以在Nuget上尝试此套餐(AuthPackage) 它使您可以轻松地为您的asp.net mvc添加身份验证。
使用Package Manager控制台安装软件包:
Install-Package AuthPackage
将连接字符串添加到(appSettings)中的Web.config:
<add key="connectionString" value="connectionStringHere" />
您已准备好注册用户,登录,注销
示例:
public async Task<ActionResult> SignIn()
{
var context = System.Web.HttpContext.Current;
AuthUser authUser = new AuthUser(context);
await authUser.SignIn("waleedchayeb2@gmail.com", "123456");
return RedirectToAction("Index", "Home");
}
您可以阅读文档here
答案 6 :(得分:0)
由于Web.config中的以下代码,我们的“意外”应用程序使用了基本身份验证:
<system.webServer>
<modules>
<remove name="FormsAuthentication" />
</modules>
... other stuff
</system.webServer>
应用程序另外配置为使用表单身份验证。 无论何时使用普通表单身份验证,都会弹出浏览器身份验证窗口。
答案 7 :(得分:0)
[BasicAuthenticationAttribute("your-username", "your-password",
BasicRealm = "your-realm")]
有两个缺点: 名称和密码是硬编码的,仅支持单用户。
更灵活的解决方案应该支持存储在配置中的多个用户名/密码对。
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);
您可以执行检查以从标题中查找用户名/密码是否存在于用户名/密码对的配置/秘密列表中
也可以创建执行基本身份验证的 HTTP 模块。您可以通过替换 CheckPassword 方法轻松插入 ASP.NET 成员资格提供程序。 https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/basic-authentication#basic-authentication-with-custom-membership
OWIN 实现示例 https://github.com/scottbrady91/Blog-Example-Classes/tree/master/OwinBasicAuthentication/WebApi
.Net 核心中的可能实现在 https://github.com/mihirdilip/aspnetcore-authentication-basic