Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net 向RESTful API添加安全性_Asp.net_Asp.net Mvc_Rest_Asp.net Apicontroller - Fatal编程技术网

Asp.net 向RESTful API添加安全性

Asp.net 向RESTful API添加安全性,asp.net,asp.net-mvc,rest,asp.net-apicontroller,Asp.net,Asp.net Mvc,Rest,Asp.net Apicontroller,我想实现两个网站,需要相互沟通。(因为其中一个站点对每个客户都有单独的部署,并且分布在许多服务器上,所以共享数据库或私下通信不是一个选项。)所以我一直在研究RESTful API 不幸的是,我遇到了很多我不熟悉的信息。一个问题是安全。我们不需要任何花哨的东西——我们不是银行或任何东西。我想我们只需要使用HTTPS和基本用户名和密码就可以了 问题: 如何将用户名和密码传递给API?它们只是作为URL中的裸参数传递吗 NET是否提供了任何授权此类用户名和密码的机制,或者我只是在每次请求时手动查看密

我想实现两个网站,需要相互沟通。(因为其中一个站点对每个客户都有单独的部署,并且分布在许多服务器上,所以共享数据库或私下通信不是一个选项。)所以我一直在研究RESTful API

不幸的是,我遇到了很多我不熟悉的信息。一个问题是安全。我们不需要任何花哨的东西——我们不是银行或任何东西。我想我们只需要使用HTTPS和基本用户名和密码就可以了

问题:

  • 如何将用户名和密码传递给API?它们只是作为URL中的裸参数传递吗

  • NET是否提供了任何授权此类用户名和密码的机制,或者我只是在每次请求时手动查看密码是否在我们的数据库中?(为了安全起见,我会散列出来。)


  • 如果您控制或对连接的双方都施加重大影响,那么客户端ssl证书是一种非常强大的方法。在这种情况下,它对我很有吸引力,因为它只需要分发一个可信的CA证书,这可以在创建客户端证书之前完成。它比任何用户名和密码都要安全得多(因为密码不需要跨越网络)

    我能想到的任何其他具有身份验证的解决方案,都必须有某种数据源来验证凭据。但是x509为您解决了这个问题。我们在应用程序之间和管理证书之外都做了这项工作,它工作得非常非常好。这基本上是最安全的东西


    一般来说,我对.net了解不多,但(不是lmgtfy)似乎是您正在寻找的逐步格式。

    如果您控制连接的双方或对其施加重大影响,则客户端ssl证书是一种非常强大的方法。在这种情况下,它对我很有吸引力,因为它只需要分发一个可信的CA证书,这可以在创建客户端证书之前完成。它比任何用户名和密码都要安全得多(因为密码不需要跨越网络)

    我能想到的任何其他具有身份验证的解决方案,都必须有某种数据源来验证凭据。但是x509为您解决了这个问题。我们在应用程序之间和管理证书之外都做了这项工作,它工作得非常非常好。这基本上是最安全的东西


    一般来说,我对.net了解不多,但(不是lmgtfy)似乎是您正在寻找的逐步格式。

    只是一个想法,它实际上取决于您所说的“用户名/密码”是什么意思。如果这意味着“授权”/“访问某个API调用”,并且您希望确保客户端被“授权”来调用您的API(只有应用程序a、B可以对API进行API调用-根据您上面的评论,这似乎就是您所寻找的):

    如上面的注释所示,使用
    JWT
    创建授权标题。有一个很好/很简单的方法

    • 这很像是一个用来签署“有效载荷”的“共享秘密”(JWT)

    • “发送方”将构建
      JWT
      并对其进行签名(并添加到标题或您想要的任何协议中-如果您喜欢它而不是
      标题,它可以是
      body

    • “接收器”将验证发送的
      JWT

      • 这包括处理/减轻“重放”——
        JWT
        spec有一个“expire”字段(
        exp
        ),您也可以让库验证(或者不验证,这取决于您)
    项目现场正在进行抽样调查


    Hth.

    只是一个想法,这实际上取决于你所说的“用户名/密码”是什么意思。如果这意味着“授权”/“访问某个API调用”,并且您希望确保客户端被“授权”来调用您的API(只有应用程序a、B可以对API进行API调用-根据您上面的评论,这似乎就是您所寻找的):

    如上面的注释所示,使用
    JWT
    创建授权标题。有一个很好/很简单的方法

    • 这很像是一个用来签署“有效载荷”的“共享秘密”(JWT

    • “发送方”将构建
      JWT
      并对其进行签名(并添加到标题或您想要的任何协议中-如果您喜欢它而不是
      标题,它可以是
      body

    • “接收器”将验证发送的
      JWT

      • 这包括处理/减轻“重放”——
        JWT
        spec有一个“expire”字段(
        exp
        ),您也可以让库验证(或者不验证,这取决于您)
    项目现场正在进行抽样调查

    如何将用户名和密码传递给API?他们会这么做吗 是否在URL中作为裸参数传递

    它可以在URL中,也可以在标题中。如果您使用的是HTTPS,那么它将全部加密,因此不会是裸的。有关更多详细信息,请参阅

    NET是否提供任何机制来授权此类用户名和密码 密码,或者我只是手动查看密码是否在我们的 每个请求上的数据库?(为了安全起见,我会散列出来。)

    不,您不需要在每次请求时检查数据库。您可以检查一次,创建一个到期的令牌,客户端可以继续向您发送令牌。这样,您就不必每次都检查数据库

    请参阅此答案以获取一些有用的信息

    我认为使用base64编码的基本身份验证就足够了。如果不是,你可以随时改变它。以下是将其应用于后端代码的不同方法:

    要将身份验证筛选器应用于控制器,请修饰cont
    [IdentityBasicAuthentication] // Enable Basic authentication for this controller.
    [Authorize] // Require authenticated requests.
    public class HomeController : ApiController
    {
        public IHttpActionResult Get() { . . . }
        public IHttpActionResult Post() { . . . }
    }
    
    [Authorize] // Require authenticated requests.
    public class HomeController : ApiController
    {
        public IHttpActionResult Get() { . . . }
    
        [IdentityBasicAuthentication] // Enable Basic authentication for this action.
        public IHttpActionResult Post() { . . . }
    }
    
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Filters.Add(new IdentityBasicAuthenticationAttribute());
    
            // Other configuration code not shown...
        }
    }
    
    using System;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Security.Principal;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web.Http.Filters;
    using BasicAuthentication.Results;
    
    namespace BasicAuthentication.Filters
    {
        public abstract class BasicAuthenticationAttribute : Attribute, IAuthenticationFilter
        {
            public string Realm { get; set; }
    
            public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
            {
                HttpRequestMessage request = context.Request;
                AuthenticationHeaderValue authorization = request.Headers.Authorization;
    
                if (authorization == null)
                {
                    // No authentication was attempted (for this authentication method).
                    // Do not set either Principal (which would indicate success) or ErrorResult (indicating an error).
                    return;
                }
    
                if (authorization.Scheme != "Basic")
                {
                    // No authentication was attempted (for this authentication method).
                    // Do not set either Principal (which would indicate success) or ErrorResult (indicating an error).
                    return;
                }
    
                if (String.IsNullOrEmpty(authorization.Parameter))
                {
                    // Authentication was attempted but failed. Set ErrorResult to indicate an error.
                    context.ErrorResult = new AuthenticationFailureResult("Missing credentials", request);
                    return;
                }
    
                Tuple<string, string> userNameAndPasword = ExtractUserNameAndPassword(authorization.Parameter);
    
                if (userNameAndPasword == null)
                {
                    // Authentication was attempted but failed. Set ErrorResult to indicate an error.
                    context.ErrorResult = new AuthenticationFailureResult("Invalid credentials", request);
                    return;
                }
    
                string userName = userNameAndPasword.Item1;
                string password = userNameAndPasword.Item2;
    
                IPrincipal principal = await AuthenticateAsync(userName, password, cancellationToken);
    
                if (principal == null)
                {
                    // Authentication was attempted but failed. Set ErrorResult to indicate an error.
                    context.ErrorResult = new AuthenticationFailureResult("Invalid username or password", request);
                }
                else
                {
                    // Authentication was attempted and succeeded. Set Principal to the authenticated user.
                    context.Principal = principal;
                }
            }
    
            protected abstract Task<IPrincipal> AuthenticateAsync(string userName, string password,
                CancellationToken cancellationToken);
    
            private static Tuple<string, string> ExtractUserNameAndPassword(string authorizationParameter)
            {
                byte[] credentialBytes;
    
                try
                {
                    credentialBytes = Convert.FromBase64String(authorizationParameter);
                }
                catch (FormatException)
                {
                    return null;
                }
    
                // The currently approved HTTP 1.1 specification says characters here are ISO-8859-1.
                // However, the current draft updated specification for HTTP 1.1 indicates this encoding is infrequently
                // used in practice and defines behavior only for ASCII.
                Encoding encoding = Encoding.ASCII;
                // Make a writable copy of the encoding to enable setting a decoder fallback.
                encoding = (Encoding)encoding.Clone();
                // Fail on invalid bytes rather than silently replacing and continuing.
                encoding.DecoderFallback = DecoderFallback.ExceptionFallback;
                string decodedCredentials;
    
                try
                {
                    decodedCredentials = encoding.GetString(credentialBytes);
                }
                catch (DecoderFallbackException)
                {
                    return null;
                }
    
                if (String.IsNullOrEmpty(decodedCredentials))
                {
                    return null;
                }
    
                int colonIndex = decodedCredentials.IndexOf(':');
    
                if (colonIndex == -1)
                {
                    return null;
                }
    
                string userName = decodedCredentials.Substring(0, colonIndex);
                string password = decodedCredentials.Substring(colonIndex + 1);
                return new Tuple<string, string>(userName, password);
            }
    
            public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
            {
                Challenge(context);
                return Task.FromResult(0);
            }
    
            private void Challenge(HttpAuthenticationChallengeContext context)
            {
                string parameter;
    
                if (String.IsNullOrEmpty(Realm))
                {
                    parameter = null;
                }
                else
                {
                    // A correct implementation should verify that Realm does not contain a quote character unless properly
                    // escaped (precededed by a backslash that is not itself escaped).
                    parameter = "realm=\"" + Realm + "\"";
                }
    
                context.ChallengeWith("Basic", parameter);
            }
    
            public virtual bool AllowMultiple
            {
                get { return false; }
            }
        }
    }