Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/29.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
C# 在Asp.NETWebAPI中对用户进行身份验证_C#_Asp.net_Asp.net Web Api_Asp.net Identity_Identity - Fatal编程技术网

C# 在Asp.NETWebAPI中对用户进行身份验证

C# 在Asp.NETWebAPI中对用户进行身份验证,c#,asp.net,asp.net-web-api,asp.net-identity,identity,C#,Asp.net,Asp.net Web Api,Asp.net Identity,Identity,我正在编写将被移动设备使用的API,我想保护这个API端点 用户身份验证详细信息由另一个名为User Manger API的应用程序(另一个包含用户详细信息的项目)提供 如何利用ASP.NET Identity framework授权和其他功能来保护我的API端点,同时从user manager API获取用户数据?问题有点广泛;基本上,您正在寻找一种策略,使用不同的现有api(该api在您的控制范围内吗,如果需要,您可以修改它吗?)对web api(dotnet core或普通框架?)的客户端

我正在编写将被移动设备使用的API,我想保护这个API端点

用户身份验证详细信息由另一个名为User Manger API的应用程序(另一个包含用户详细信息的项目)提供


如何利用ASP.NET Identity framework授权和其他功能来保护我的API端点,同时从user manager API获取用户数据?

问题有点广泛;基本上,您正在寻找一种策略,使用不同的现有api(该api在您的控制范围内吗,如果需要,您可以修改它吗?)对web api(dotnet core或普通框架?)的客户端进行身份验证和授权


如果你可以修改这两个,我会说通过StackOverflow和Google查找JWT令牌、OAuth和identity server;基本上,您正在寻找一种策略,使用不同的现有api(该api在您的控制范围内吗,如果需要,您可以修改它吗?)对web api(dotnet core或普通框架?)的客户端进行身份验证和授权


如果您可以同时修改这两个属性,我会说通过StackOverflow和Google查找JWT令牌、OAuth和identity server。

1-您可以实现一个属性并装饰您的api控制器

2-您可以在asp.net的app_start中实现并注册全局筛选器(并确保您正在global.asax中注册筛选器)

3-您可以执行Roel Abspoel提到的操作,在您的User Manager API中实现Identity Server,让您的客户机与之对话并获取令牌,然后您的API与之对话以验证令牌

还有其他方法,但我会保持简短和甜蜜

以下是使用属性的示例:

using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Filters;

namespace myExample
{
    public class ExternalAuthenticationAttribute : IAuthenticationFilter
    {
        public virtual bool AllowMultiple
        {
            get { return false; }
        }

        public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
        {
            // get request + authorization headers
            HttpRequestMessage request = context.Request;
            AuthenticationHeaderValue authorization = request.Headers.Authorization;

            // check for username and password (regardless if it was validated on the client, server should check)
            // this will only accept Basic Authorization
            if (String.IsNullOrEmpty(authorization.Parameter) || authorization.Scheme != "Basic")
            {
                // Authentication was attempted but failed. Set ErrorResult to indicate an error.
                context.ErrorResult = new AuthenticationFailureResult("Missing credentials", request);
                return null;
            }
            var userNameAndPasword = GetCredentials(authorization.Parameter);
            if (userNameAndPasword == null)
            {
                // Authentication was attempted but failed. Set ErrorResult to indicate an error.
                context.ErrorResult = new AuthenticationFailureResult("Could not get credentials", request);
                return null;
            }

            // now that we have the username + password call User manager API
            var client = new HttpClient();
            // POST USERNAME + PASSWORD INSIDE BODY, not header, not query string. ALSO USE HTTPS to make sure it is sent encrypted
            var response = AuthenticateAgainstUserMapagerApi1(userNameAndPasword, client);

            // THIS WILL WORK IN .NET CORE 1.1. ALSO USE HTTPS to make sure it is sent encrypted
            //var response = AuthenticateAgainstUserMapagerApi2(client, userNameAndPasword);

            // parse response
            if (!response.IsSuccessStatusCode)
            {
                context.ErrorResult = new AuthenticationFailureResult("Invalid username or password", request);
            }
            else
            {
                var readTask = response.Content.ReadAsStringAsync();
                var content = readTask.Result;
                context.Principal = GetPrincipal(content); // if User manager API returns a user principal as JSON we would 
            }

            return null;
        }

        //private static HttpResponseMessage AuthenticateAgainstUserMapagerApi2(HttpClient client, Tuple<string, string> userNameAndPasword)
        //{
        //    client.SetBasicAuthentication(userNameAndPasword.Item1, userNameAndPasword.Item2);
        //    var responseTask = client.GetAsync("https://your_user_manager_api_URL/api/authenticate");
        //    return responseTask.Result;
        //}

        private static HttpResponseMessage AuthenticateAgainstUserMapagerApi1(Tuple<string, string> userNameAndPasword, HttpClient client)
        {
            var credentials = new
            {
                Username = userNameAndPasword.Item1,
                Password = userNameAndPasword.Item2
            };
            var responseTask = client.PostAsJsonAsync("https://your_user_manager_api_URL/api/authenticate", credentials);
            var response = responseTask.Result;
            return response;
        }

        public IPrincipal GetPrincipal(string principalStr)
        {
            // deserialize principalStr and return a proper Principal instead of ClaimsPrincipal below
            return new ClaimsPrincipal();
        }

        private static Tuple<string, string> GetCredentials(string authorizationParameter)
        {
            byte[] credentialBytes;

            try
            {
                credentialBytes = Convert.FromBase64String(authorizationParameter);
            }
            catch (FormatException)
            {
                return null;
            }

            try
            {
                // make sure you use the proper encoding which match client
                var encoding = Encoding.ASCII;
                string decodedCredentials;
                decodedCredentials = encoding.GetString(credentialBytes);
                int colonIndex = decodedCredentials.IndexOf(':');
                string userName = decodedCredentials.Substring(0, colonIndex);
                string password = decodedCredentials.Substring(colonIndex + 1);
                return new Tuple<string, string>(userName, password);
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }
    }

    public class AuthenticationFailureResult : IHttpActionResult
    {
        public AuthenticationFailureResult(string reasonPhrase, HttpRequestMessage request)
        {
            ReasonPhrase = reasonPhrase;
            Request = request;
        }

        public string ReasonPhrase { get; private set; }

        public HttpRequestMessage Request { get; private set; }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            return Task.FromResult(Execute());
        }

        private HttpResponseMessage Execute()
        {
            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
            response.RequestMessage = Request;
            response.ReasonPhrase = ReasonPhrase;
            return response;
        }
    }
}

1-您可以实现一个属性并装饰您的api控制器

2-您可以在asp.net的app_start中实现并注册全局筛选器(并确保您正在global.asax中注册筛选器)

3-您可以执行Roel Abspoel提到的操作,在您的User Manager API中实现Identity Server,让您的客户机与之对话并获取令牌,然后您的API与之对话以验证令牌

还有其他方法,但我会保持简短和甜蜜

以下是使用属性的示例:

using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Filters;

namespace myExample
{
    public class ExternalAuthenticationAttribute : IAuthenticationFilter
    {
        public virtual bool AllowMultiple
        {
            get { return false; }
        }

        public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
        {
            // get request + authorization headers
            HttpRequestMessage request = context.Request;
            AuthenticationHeaderValue authorization = request.Headers.Authorization;

            // check for username and password (regardless if it was validated on the client, server should check)
            // this will only accept Basic Authorization
            if (String.IsNullOrEmpty(authorization.Parameter) || authorization.Scheme != "Basic")
            {
                // Authentication was attempted but failed. Set ErrorResult to indicate an error.
                context.ErrorResult = new AuthenticationFailureResult("Missing credentials", request);
                return null;
            }
            var userNameAndPasword = GetCredentials(authorization.Parameter);
            if (userNameAndPasword == null)
            {
                // Authentication was attempted but failed. Set ErrorResult to indicate an error.
                context.ErrorResult = new AuthenticationFailureResult("Could not get credentials", request);
                return null;
            }

            // now that we have the username + password call User manager API
            var client = new HttpClient();
            // POST USERNAME + PASSWORD INSIDE BODY, not header, not query string. ALSO USE HTTPS to make sure it is sent encrypted
            var response = AuthenticateAgainstUserMapagerApi1(userNameAndPasword, client);

            // THIS WILL WORK IN .NET CORE 1.1. ALSO USE HTTPS to make sure it is sent encrypted
            //var response = AuthenticateAgainstUserMapagerApi2(client, userNameAndPasword);

            // parse response
            if (!response.IsSuccessStatusCode)
            {
                context.ErrorResult = new AuthenticationFailureResult("Invalid username or password", request);
            }
            else
            {
                var readTask = response.Content.ReadAsStringAsync();
                var content = readTask.Result;
                context.Principal = GetPrincipal(content); // if User manager API returns a user principal as JSON we would 
            }

            return null;
        }

        //private static HttpResponseMessage AuthenticateAgainstUserMapagerApi2(HttpClient client, Tuple<string, string> userNameAndPasword)
        //{
        //    client.SetBasicAuthentication(userNameAndPasword.Item1, userNameAndPasword.Item2);
        //    var responseTask = client.GetAsync("https://your_user_manager_api_URL/api/authenticate");
        //    return responseTask.Result;
        //}

        private static HttpResponseMessage AuthenticateAgainstUserMapagerApi1(Tuple<string, string> userNameAndPasword, HttpClient client)
        {
            var credentials = new
            {
                Username = userNameAndPasword.Item1,
                Password = userNameAndPasword.Item2
            };
            var responseTask = client.PostAsJsonAsync("https://your_user_manager_api_URL/api/authenticate", credentials);
            var response = responseTask.Result;
            return response;
        }

        public IPrincipal GetPrincipal(string principalStr)
        {
            // deserialize principalStr and return a proper Principal instead of ClaimsPrincipal below
            return new ClaimsPrincipal();
        }

        private static Tuple<string, string> GetCredentials(string authorizationParameter)
        {
            byte[] credentialBytes;

            try
            {
                credentialBytes = Convert.FromBase64String(authorizationParameter);
            }
            catch (FormatException)
            {
                return null;
            }

            try
            {
                // make sure you use the proper encoding which match client
                var encoding = Encoding.ASCII;
                string decodedCredentials;
                decodedCredentials = encoding.GetString(credentialBytes);
                int colonIndex = decodedCredentials.IndexOf(':');
                string userName = decodedCredentials.Substring(0, colonIndex);
                string password = decodedCredentials.Substring(colonIndex + 1);
                return new Tuple<string, string>(userName, password);
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }
    }

    public class AuthenticationFailureResult : IHttpActionResult
    {
        public AuthenticationFailureResult(string reasonPhrase, HttpRequestMessage request)
        {
            ReasonPhrase = reasonPhrase;
            Request = request;
        }

        public string ReasonPhrase { get; private set; }

        public HttpRequestMessage Request { get; private set; }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            return Task.FromResult(Execute());
        }

        private HttpResponseMessage Execute()
        {
            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
            response.RequestMessage = Request;
            response.ReasonPhrase = ReasonPhrase;
            return response;
        }
    }
}

这两个项目都是用.net技术创建的。身份验证项目(我无法修改此项目)像普通identity framework操作方法一样公开端点。有用于生成令牌的端点等。这两个项目都是在.net技术中创建的。身份验证项目(我无法修改此项目)像普通的identity framework操作方法一样公开端点—有用于生成令牌的端点,等等。