3Web Api 身份验证

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3Web Api 身份验证相关的知识,希望对你有一定的参考价值。

 由于接口传递的是企业内部数据,在数据安全性方面需要把控,因此当客户端调用接口时,必须提供身份标识,验证通过之后方可调用接口,以确保数据的安全性。由于WebApi的身份校验是面向切面编程的,即当你需要进行身份校验时,执行逻辑为:Client->Filter身份校验->接口,当校验通过时,即可正常调用

当校验不通过时,将返回401身份验证失败。

一、身份校验 Basic

1、在Api项目下创建Filter文件夹

2、编写验证程序

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

namespace SCM.API
{
    public class APIAuthorizeAttribute :AuthorizationFilterAttribute
    {
        public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            base.OnAuthorization(actionContext);

            if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
            {
                return;
            }

            var authHeader = actionContext.Request.Headers.Authorization;

            if (authHeader != null)
            {
                if (authHeader.Scheme.Equals("basic", StringComparison.OrdinalIgnoreCase) && !String.IsNullOrWhiteSpace(authHeader.Parameter))
                {
                    var credArrar = GetCredentials(authHeader);
                    var userName = credArrar[0];
                    var key = credArrar[1];
                    string ip = System.Web.HttpContext.Current.Request.UserHostAddress;
                    if (1 == 1) //!IsresourceOwner(userName, actionContext)
                    {
                        if (APIAuthorizeInfoValidate.ValidateApi(userName, key))
                        {
                            var currentPrincipal = new GenericPrincipal(new GenericIdentity(userName), null);
                            Thread.CurrentPrincipal = currentPrincipal;
                            return;
                        }
                    }
                }
            }
            HandleUnauthorizeRequest(actionContext);
        }

        private string[] GetCredentials(System.Net.Http.Headers.AuthenticationHeaderValue authHeader)
        {
            //Base 64 encoded string
            var rawCred = authHeader.Parameter;
            var encoding = Encoding.GetEncoding("iso-8859-1");
            var cred = encoding.GetString(Convert.FromBase64String(rawCred));

            var credArray = cred.Split(\':\');
            return credArray;
        }

        private bool IsresourceOwner(string username, System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            var routeData = actionContext.Request.GetRouteData();
            var resourceUsername = routeData.Values["username"] as string;

            if (resourceUsername == username)
            {
                return true;
            }
            return false;
        }

        private void HandleUnauthorizeRequest(System.Web.Http.Controllers.HttpActionContext ActionContext)
        {
            
            ActionContext.Response = ActionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            ActionContext.Response.Headers.Add("WWW-Authenticate", "Basic Scheme=\'eLearning\' location=\'http://192.168.60.31:81/help\'");
        }
    }
}
View Code APIAuthorizeAttribute
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using Newtonsoft.Json;
using SCM.API.Common;
using System.Data.OracleClient;

namespace SCM.API
{
    public class APIAuthorizeInfo
    {
        public string api_usr_user { get; set; }
        public string api_key { get; set; }
    }

    public class APIAuthorizeInfoValidate
    {
        [DllImport("Iphlpapi.dll")]

        static extern int SendARP(Int32 DestIP, Int32 SrcIP, ref Int64 MacAddr, ref Int32 PhyAddrLen);
        [DllImport("Ws2_32.dll")]

        static extern Int32 inet_addr(string ipaddr);

        /// <summary>
        /// 身份验证:用户、口令、IP、MAC
        /// </summary>
        /// <param name="username">用户名</param>
        /// <param name="key">口令</param>
        /// <param name="ip">IP</param>
        /// <param name="mac">MAC</param>
        /// <returns></returns>
        public static bool ValidateApi(string username, string key)
        {
            string ip = APIAuthorizeInfoValidate.GetWebClientIp();   //获取用户IP
            string mac = APIAuthorizeInfoValidate.GetMacAddress(ip);   //获取用户MAC地址
            WebConfigHelper con = new WebConfigHelper();
            var _APIAuthorizeInfo = JsonConvert.DeserializeObject<List<APIAuthorizeInfo>>(WebConfigHelper.ApiAuthorize);
            var ips = WebConfigHelper.IPs.Contains(",") ? WebConfigHelper.IPs.Split(\',\') : new string[] { WebConfigHelper.IPs };
            var macs = WebConfigHelper.Macs.Contains(",") ? WebConfigHelper.Macs.Split(\',\') : new string[] { WebConfigHelper.Macs };
            if (_APIAuthorizeInfo != null && _APIAuthorizeInfo.Count > 0)
            {
                foreach (var v in _APIAuthorizeInfo)
                {
                  //  if ( v.api_usr_user == username && v.api_key == key && ips.Contains(ip) && macs.Contains(mac) )
                    if (v.api_usr_user == username && v.api_key == key )
                    {
                        string sql = @"update api_mstr set api_rmks = :api_rmks where API_USR_USER = :API_USR_USER";
                        OracleParameter[] pars = {
                                                     new OracleParameter("api_rmks",OracleType.VarChar),
                                                     new OracleParameter("API_USR_USER",OracleType.VarChar)
                                                 };
                        pars[0].Value = ip;
                        pars[1].Value = v.api_usr_user;
                        int i = OracleHelper.ExecuteSql(sql,pars);
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 身份验证:用户、口令、IP
        /// </summary>
        /// <param name="username"></param>
        /// <param name="key"></param>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static bool ValidateApi(string username, string key, string ip)
        {
            ip = GetWebClientIp(); //获取用户内部IP
            WebConfigHelper con = new WebConfigHelper();
            var _APIAuthorizeInfo = JsonConvert.DeserializeObject<List<APIAuthorizeInfo>>(WebConfigHelper.ApiAuthorize);
            var ips = WebConfigHelper.IPs.Contains(",") ? WebConfigHelper.IPs.Split(\',\') : new string[] { WebConfigHelper.IPs };
            if (_APIAuthorizeInfo != null && _APIAuthorizeInfo.Count > 0)
            {
                foreach (var v in _APIAuthorizeInfo)
                {
                    if (v.api_usr_user == username && v.api_key == key && ips.Contains(ip))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        ///<summary>  
        /// SendArp获取MAC地址  
        ///</summary>  
        ///<param name="RemoteIP">目标机器的IP地址如(192.168.1.1)</param>  
        ///<returns>目标机器的mac 地址</returns>  
        public static string GetMacAddress(string RemoteIP)
        {

            StringBuilder macAddress = new StringBuilder();

            try
            {
                Int32 remote = inet_addr(RemoteIP);
                Int64 macInfo = new Int64();
                Int32 length = 6;
                SendARP(remote, 0, ref macInfo, ref length);
                string temp = Convert.ToString(macInfo, 16).PadLeft(12, \'0\').ToUpper();
                int x = 12;
                for (int i = 0; i < 6; i++)
                {
                    if (i == 5)
                    {
                        macAddress.Append(temp.Substring(x - 2, 2));
                    }
                    else
                    {
                        macAddress.Append(temp.Substring(x - 2, 2) + "-");
                    }

                    x -= 2;
                }
                return macAddress.ToString();
            }
            catch
            {
                return macAddress.ToString();
            }
        }

        /// <summary>
        /// 获取用户IP
        /// </summary>
        /// <returns></returns>
        public static string GetWebClientIp()
        {
            string userIP = "";

            try
            {
                if (System.Web.HttpContext.Current == null
            || System.Web.HttpContext.Current.Request == null
            || System.Web.HttpContext.Current.Request.ServerVariables == null)
                    return "";

                string CustomerIP = "";

                //CDN加速后取到的IP   
                CustomerIP = System.Web.HttpContext.Current.Request.Headers["Cdn-Src-Ip"];
                if (!string.IsNullOrEmpty(CustomerIP))
                {
                    return CustomerIP;
                }

                CustomerIP = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];


                if (!String.IsNullOrEmpty(CustomerIP))
                    return CustomerIP;

                if (System.Web.HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
                {
                    CustomerIP = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                    if (CustomerIP == null)
                        CustomerIP = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
                }
                else
                {
                    CustomerIP = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

                }

                if (string.Compare(CustomerIP, "unknown", true) == 0)
                    return System.Web.HttpContext.Current.Request.UserHostAddress;
                return CustomerIP;
            }
            catch { }

            return userIP;
        }

        public static string GetWebClientIp1()
        {
            try
            {
                string result = String.Empty;
                result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                if (result != null && result != String.Empty)
                {
                    //可能有代理
                    if (result.IndexOf(".") == -1)    //没有“.”肯定是非IPv4格式
                        result = null;
                    else
                    {
                        if (result.IndexOf(",") != -1)
                        {
                            //有“,”,估计多个代理。取第一个不是内网的IP。
                            result = result.Replace(" ", "").Replace("\'", "");
                            string[] temparyip = result.Split(",;".ToCharArray());
                            for (int i = 0; i < temparyip.Length; i++)
                            {
                                if (IsIPAddress(temparyip[i])
                                    && temparyip[i].Substring(0, 3) != "10."
                                    && temparyip[i].Substring(0, 7) != "192.168"
                                    && temparyip[i].Substring(0, 7) != "172.16.")
                                {
                                    return temparyip[i];    //找到不是内网的地址
                                }
                            }
                        }
                        else if (IsIPAddress(result)) //代理即是IP格式 ,IsIPAddress判断是否是IP的方法,
                            return result;
                        else
                            result = null;    //代理中的内容 非IP,取IP
                    }

                }

                string IpAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null && HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != String.Empty) ? HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] : HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

                if (null == result || result == String.Empty)
                    result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

                if (result == null || result == String.Empty)
                    result = HttpContext.Current.Request.UserHostAddress;

                return result;
            }
            catch 
            {
                return null;
            }
        }


        #region bool IsIPAddress(str1) 判断是否是IP格式
        /**/
        /// <summary>  
        /// 判断是否是IP地址格式 0.0.0.0  
        /// </summary>  
        /// <param name="str1">待判断的IP地址</param>  
        /// <returns>true or false</returns>  
        public static bool IsIPAddress(string str1)
        {
            if (str1 == null || str1 == string.Empty || str1.Length < 7 || str1.Length > 15) return false;
            string regformat = @"^\\d{1,3}[\\.]\\d{1,3}[\\.]\\d{1,3}[\\.]\\d{1,3}$";
            Regex regex = new Regex(regformat, RegexOptions.IgnoreCase);
            return regex.IsMatch(str1);
        }
        #endregion
    }
}
View Code APIAuthorizeInfoValidate
using System.Data;
using System.Data.OracleClient;

namespace SCM.API.Common
{
    public class WebConfigHelper
    {
        public static string ApiAuthorize { get; set; }
        public static string IPs { get; set; }
        public static string Macs { get; set; }

        public WebConfigHelper()
        {
            string sql = @"select * from api_mstr";
            using (OracleConnection conn = new OracleConnection(GetConnString.ConnectionString))
            {
                conn.Open();
                OracleCommand cmd = new OracleCommand(sql, conn);
                OracleDataAdapter myda = new OracleDataAdapter(cmd);
                DataTable dt = new DataTable();
                myda.Fill(dt);
                ApiAuthorize = "[";
                for (int i = 0; i <= dt.Rows.Count - 1; i++)
                {
                    ApiAuthorize += "{api_usr_user :\'" + dt.Rows[i]["api_usr_user"].ToString()+"\',";
                    ApiAuthorize += "api_key :\'" + dt.Rows[i]["api_key"].ToString() + "\'},";
                    IPs += dt.Rows[i]["api_ip"].ToString() + ",";
                    Macs += dt.Rows[i]["api_mac"].ToString() + ",";
                }
                IPs = IPs.Substring(0, IPs.Length - 1);
                Macs = Macs.Substring(0, Macs.Length - 1);
                ApiAuthorize = ApiAuthorize.Substring(0, ApiAuthorize.Length - 1);
                ApiAuthorize += "]";
                myda.Dispose();
            }
        }
    }
}
View Code WebConfigHelper

配置全局变量

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace SCM.API
{
    // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
    // 请访问 http://go.microsoft.com/?LinkId=9394801

    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            
            HandlerConfig.RegisterHandlers(GlobalConfiguration.Configuration.MessageHandlers);
            // 使api返回为json 
            GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
            GlobalConfiguration.Configuration.Filters.Add(new APIAuthorizeAttribute());
        }
    }
}
View Code Global.asax

配置WebApiConfig

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace SCM.API
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            //配置返回的时间类型数据格式
            ReturnJsonSerialiZerSettings();
            

            config.Filters.Add(new APIAuthorizeAttribute());
        }

        /// <summary>
        /// 返回Json序列化设置
        /// </summary>
        private static void ReturnJsonSerialiZerSettings()
        {
            var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
            json.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Local;
            json.SerializerSettings.DateFormatString = "yyyy\'-\'MM\'-\'dd\' \'HH\':\'mm\':\'ss";
            json.SerializerSettings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
        }
    }
}
View Code WebApiConfig

3、测试

 

以上是关于3Web Api 身份验证的主要内容,如果未能解决你的问题,请参考以下文章

教程4 - 验证和权限

Django REST框架--认证和权限

如何在我当前使用 Spotify Search API 的代码上应用 Spotify API 身份验证?

Web 应用程序安全和客户端身份验证

通过 Google 打开 auth 2.0 身份验证后重定向 url 无效

在 ReactJS 中的 Spotify API 上为 PKCE 身份验证创建代码验证器和质询