zoukankan      html  css  js  c++  java
  • ASP.NET Web API Basic Identity 中的基本身份验证

    缺点

    • 用户凭证在请求中发送。
    • 凭据作为明文发送。
    • 每个请求都会发送凭据。
    • 无法注销,除非结束浏览器会话。
    • 易于跨站点请求伪造(CSRF); 需要反CSRF措施。

    优点

    • 互联网标准。
    • 受所有主要浏览器支持。
    • 相对简单的协议。

    基本认证的工作原理如下:

    1. 如果请求需要认证,则服务器返回401(未授权)。响应包括WWW-Authenticate头,指示服务器支持基本身份验证。
    2. 客户端发送另一个请求,其中的客户端凭证位于授权头中。凭据的格式为字符串“name:password”,base64编码。凭证未加密。

    基本认证在“领域”的上下文中执行。服务器包括WWW-Authenticate头中的领域名称。用户的凭据在该领域内有效。领域的确切范围由服务器定义。例如,您可以定义多个领域以分区资源。

    因为凭据是未加密发送的,所以基本身份验证仅通过HTTPS安全。请参阅在Web API中使用SSL

    基本认证也容易受到CSRF攻击。在用户输入凭据后,浏览器会在会话持续期间自动将它们发送到同一域的后续请求。这包括AJAX请求。请参阅防止跨站点请求伪造(CSRF)攻击

    使用IIS的基本身份验证

    IIS支持基本身份验证,但是有一个警告:用户根据其Windows凭据进行身份验证。这意味着用户必须在服务器的域上有一个帐户。对于面向公众的网站,通常需要对ASP.NET成员资格提供程序进行身份验证。1

    要使用IIS启用基本身份验证,请在ASP.NET项目的Web.config中将身份验证模式设置为“Windows”:

    复制
    xml
    <system.web>
        <authentication mode="Windows" />
    </system.web>
    

    在此模式下,IIS使用Windows凭据进行身份验证。此外,您必须在IIS中启用基本身份验证。在IIS管理器中,转到功能视图,选择验证,然后启用基本验证。

    在Web API项目中,[Authorize]为需要验证的任何控制器操作添加属性。

    客户端通过在请求中设置Authorization头来验证自身。浏览器客户端自动执行此步骤。非浏览器客户端将需要设置标头。

    使用自定义成员资格的基本身份验证

    如上所述,IIS内置的基本身份验证使用Windows凭据。这意味着您需要在托管服务器上为您的用户创建帐户。但对于互联网应用程序,用户帐户通常存储在外部数据库中。

    以下代码如何执行基本身份验证的HTTP模块。您可以通过替换CheckPassword方法来轻松插入ASP.NET成员资格提供程序,该方法在本示例中是一个虚拟方法。

    在Web API 2中,应考虑编写身份验证过滤器OWIN中间件,而不是HTTP模块。

    复制
    C#
    namespace WebHostBasicAuth.Modules
    {
        public class BasicAuthHttpModule : IHttpModule
        {
            private const string Realm = "My Realm";
    
            public void Init(HttpApplication context)
            {
                // Register event handlers
                context.AuthenticateRequest += OnApplicationAuthenticateRequest;
                context.EndRequest += OnApplicationEndRequest;
            }
    
            private static void SetPrincipal(IPrincipal principal)
            {
                Thread.CurrentPrincipal = principal;
                if (HttpContext.Current != null)
                {
                    HttpContext.Current.User = principal;
                }
            }
    
            // TODO: Here is where you would validate the username and password.
            private static bool CheckPassword(string username, string password)
            {
                return username == "user" && password == "password";
            }
    
            private static void AuthenticateUser(string credentials)
            {
                try
                {
                    var encoding = Encoding.GetEncoding("iso-8859-1");
                    credentials = encoding.GetString(Convert.FromBase64String(credentials));
    
                    int separator = credentials.IndexOf(':');
                    string name = credentials.Substring(0, separator);
                    string password = credentials.Substring(separator + 1);
    
                    if (CheckPassword(name, password))
                    {
                        var identity = new GenericIdentity(name);
                        SetPrincipal(new GenericPrincipal(identity, null));
                    }
                    else
                    {
                        // Invalid username or password.
                        HttpContext.Current.Response.StatusCode = 401;
                    }
                }
                catch (FormatException)
                {
                    // Credentials were not formatted correctly.
                    HttpContext.Current.Response.StatusCode = 401;
                }
            }
    
            private static void OnApplicationAuthenticateRequest(object sender, EventArgs e)
            {
                var request = HttpContext.Current.Request;
                var authHeader = request.Headers["Authorization"];
                if (authHeader != null)
                {
                    var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);
    
                    // RFC 2617 sec 1.2, "scheme" name is case-insensitive
                    if (authHeaderVal.Scheme.Equals("basic",
                            StringComparison.OrdinalIgnoreCase) &&
                        authHeaderVal.Parameter != null)
                    {
                        AuthenticateUser(authHeaderVal.Parameter);
                    }
                }
            }
    
            // If the request was unauthorized, add the WWW-Authenticate header 
            // to the response.
            private static void OnApplicationEndRequest(object sender, EventArgs e)
            {
                var response = HttpContext.Current.Response;
                if (response.StatusCode == 401)
                {
                    response.Headers.Add("WWW-Authenticate",
                        string.Format("Basic realm="{0}"", Realm));
                }
            }
    
            public void Dispose() 
            {
            }
        }
    }
    

    要启用HTTP模块,添加以下在你的web.config文件system.webServer部分:+

    复制
    xml
    <system.webServer>
        <modules>
          <add name="BasicAuthHttpModule" 
            type="WebHostBasicAuth.Modules.BasicAuthHttpModule, YourAssemblyName"/>
        </modules>
    

    将“YourAssemblyName”替换为程序集的名称(不包括“dll”扩展名)。

    您应该禁用其他身份验证方案,例如Forms或Windows身份验证。

  • 相关阅读:
    运算符、流程控制
    python数据类型
    Python入门基础
    pandas教程1:pandas数据结构入门
    使用matplotlib绘制多轴图
    使用matplotlib快速绘图
    浙江省新高中信息技术教材,将围绕Python进行并增加编程相关知识点
    [转]ubuntu搭建LAMP环境
    [转]字体精简
    [转]安装PIL时注册表中找不到python2.7
  • 原文地址:https://www.cnblogs.com/Javi/p/6558262.html
Copyright © 2011-2022 走看看