zoukankan      html  css  js  c++  java
  • WebAPI接口安全校验

    通过网上查看相关WebAPI接口验证的方法,整理了一下,直接上代码,功能不复杂,有问题留言,

    //-----------------------------------------------------------------------
    // <copyright file="ApiAuthenticationFilter.cs" company="FenSiShengHuo, Ltd.">
    //     Copyright (c) 2018 , All rights reserved.
    // </copyright>
    //-----------------------------------------------------------------------
    
    using System;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Security.Principal;
    using System.Threading;
    using System.Web.Http.Controllers;
    using System.Web.Http.Filters;
    
    namespace DotNet.WeChat.API.Attribute
    {
        using DotNet.Business;
        using DotNet.Model;
        using DotNet.Utilities;
    
        /// <summary>
        /// ApiAuthenticationFilter
        /// 
        /// 2018-07-19 版本:1.0 JiShiYu 创建。    
        ///
        /// <author>
        ///        <name>JiShiYu</name>
        ///        <date>2018-07-19</date>
        /// </author> 
        /// </summary>
        public class ApiAuthenticationFilter : AuthorizationFilterAttribute
        {
            public override void OnAuthorization(HttpActionContext filterContext)
            {
                // 判断是否是不做授权检查的
                var apiNoAuthenticationFilter = filterContext.ActionDescriptor.GetCustomAttributes<ApiNoAuthenticationFilter>();
                if (apiNoAuthenticationFilter != null && apiNoAuthenticationFilter.Any())
                {
                    return;
                }
    
                BaseResult result = null;
                var identity = ParseHeader(filterContext, out result); //取得資料內容
                if (identity == null)
                {
                    ChallengeAuthRequest(filterContext, result); //回傳錯誤訊息
                    return;
                }
                var genericPrincipal = new GenericPrincipal(identity, null);
                //  在认证成功后将认证身份设置给当前线程中Principal属性
                Thread.CurrentPrincipal = genericPrincipal;
                result = OnAuthorizeUser(identity, filterContext);
                if (!result.Status)
                {
                    ChallengeAuthRequest(filterContext, result);
                    return;
                }
            }
    
            /// <summary>
            /// 定义一个方法便校验,并将其修饰为虚方法,以免后续要添加其他有关用户数据
            /// </summary>
            /// <param name="appKey"></param>
            /// <param name="appSecret"></param>
            /// <param name="token"></param>
            /// <param name="actionContext"></param>
            /// <returns></returns>
            protected virtual BaseResult OnAuthorizeUser(BasicAuthenticationIdentity identity, HttpActionContext actionContext)
            {
                BaseResult result = new BaseResult();
                result.Status = false;
                result.StatusCode = Status.ParameterError.ToString();
    
                if (string.IsNullOrWhiteSpace(identity.SystemCode))
                {
                    result.Status = false;
                    result.StatusCode = Status.ParameterError.ToString();
                    result.StatusMessage = "systemCode " + Status.ParameterError.ToDescription();
                    return result;
                }
                // 判断参数
                if (identity.UserInfo != null)
                {
                    // 防止伪造、判断用户的有效性
                    if (!ServiceUtil.VerifySignature(identity.UserInfo))
                    {
                        result.StatusCode = Status.SignatureError.ToString();
                        result.StatusMessage = "userInfo " + Status.SignatureError.ToDescription();
                        return result;
                    }
                    // 这里需要是已经登录的用户,不是已经被踢掉的用户
                    if (!Utilities.ValidateOpenId(identity.UserInfo.Id, identity.UserInfo.OpenId))
                    {
                        result.StatusCode = Status.SignatureError.ToString();
                        result.StatusMessage = "OpenId " + Status.SignatureError.ToDescription();
                        return result;
                    }
                }
                else
                {
                    string ipAddress = Utilities.GetIPAddress(true);
                    // 检查是否为内部ip地址发送出去的手机短信  
                    //if (onlyLocalIp)
                    //{
                    //    if (!IpHelper.IsLocalIp(ipAddress))
                    //    {
                    //        // 不是内网发出的, 也不是信任的ip列表里的,直接给拒绝发送出去
                    //        result.Status = false;
                    //        result.StatusCode = Status.ErrorIPAddress.ToString();
                    //        result.StatusMessage = ipAddress + " " + Status.ErrorIPAddress.ToDescription();
                    //    }
                    //}
    
                    if (string.IsNullOrWhiteSpace(identity.AppKey))
                    {
                        result.StatusCode = Status.ParameterError.ToString();
                        result.StatusMessage = "appKey " + Status.ParameterError.ToDescription();
                        return result;
                    }
                    if (string.IsNullOrWhiteSpace(identity.Signature))
                    {
                        result.StatusCode = Status.ParameterError.ToString();
                        result.StatusMessage = "signature " + Status.ParameterError.ToDescription();
                        return result;
                    }
    
                    if (string.IsNullOrWhiteSpace(identity.TimeSpan))
                    {
                        result.StatusCode = Status.ParameterError.ToString();
                        result.StatusMessage = "TimeSpan " + Status.ParameterError.ToDescription();
                        return result;
                    }
                    else
                    {
                        long unixTimeStamp;
                        if (long.TryParse(identity.TimeSpan, out unixTimeStamp))
                        {
                            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); // 当地时区
                            DateTime dtStart = startTime.AddSeconds(unixTimeStamp);
                            TimeSpan ts = DateTime.Now - dtStart;
                            if (ts.TotalMinutes > 5)
                            {
                                result.StatusCode = Status.ParameterError.ToString();
                                result.StatusMessage = "请求时间已过期,请检查请求服务器时间,传递当前时间戳";
                                return result;
                            }
                        }
                        else
                        {
                            result.StatusCode = Status.ParameterError.ToString();
                            result.StatusMessage = "TimeSpan时间戳参数错误,传递当前时间戳";
                            return result;
                        }
                    }
                    //  AppSecret 不应该传
                    //if (string.IsNullOrWhiteSpace(identity.AppSecret))
                    //{
                    //    result.StatusCode = Status.ParameterError.ToString();
                    //    result.StatusMessage = "appSecret " + Status.ParameterError.ToDescription();
                    //    return result;
                    //}
                    // 取服务器上的
                    var secret = BaseServicesLicenseManager.GetSecretByKeyByCache(identity.AppKey);
                    if (string.IsNullOrWhiteSpace(secret))
                    {
                        result.StatusCode = Status.ParameterError.ToString();
                        result.StatusMessage = "找不到appKey的密钥";
                        return result;
                    }
                    else
                    {
                        string serverSignature = System.Web.HttpUtility.UrlEncode(SecretUtilitiesBase.md5(identity.AppKey + identity.TimeSpan + secret));
                        if (!string.Equals(identity.Signature, serverSignature))
                        {
                            result.StatusCode = Status.ParameterError.ToString();
                            result.StatusMessage = "Signature 签名不正确";
                            return result;
                        }
                    }
    
                    result = BaseServicesLicenseManager.CheckService(identity.AppKey, secret, true, false, 0, 0, identity.SystemCode, identity.PermissionCode);
                    if (result.Status)
                    {
                        // 从接口确定当前调用者
                        BaseUserEntity userEntity = BaseUserManager.GetObjectByCodeByCache(identity.AppKey, true);
                        if (userEntity != null)
                        {
                            BaseUserInfo userInfo = new BaseUserInfo();
                            userInfo.Id = userEntity.Id;
                            userInfo.Code = userEntity.Code;
                            userInfo.UserName = userEntity.UserName;
                            userInfo.NickName = userEntity.NickName;
                            userInfo.RealName = userEntity.RealName;
                            userInfo.CompanyId = userEntity.CompanyId;
                            userInfo.CompanyCode = userEntity.CompanyCode;
                            userInfo.CompanyName = userEntity.CompanyName;
                            userInfo.IPAddress = ipAddress;
                            identity.UserInfo = userInfo;
                        }
                    }
                }
    
                return result;
            }
    
            /// <summary>
            /// 解析Headers
            /// </summary>
            /// <param name="filterContext"></param>
            /// <returns></returns>
            protected virtual BasicAuthenticationIdentity ParseHeader(HttpActionContext filterContext, out BaseResult result)
            {
                BasicAuthenticationIdentity authenticationIdentity = null;
                result = new BaseResult();
                BaseUserInfo userInfo = null;
                string systemCode = string.Empty;
                string appKey = string.Empty;
                string timeSpan = string.Empty;
                string signature = string.Empty;
                string permissionCode = string.Empty;
                string userInfoStr = string.Empty;
                try
                {
                    var re = filterContext.Request;
                    var headers = re.Headers;
                    if (headers.Contains("systemCode"))
                    {
                        systemCode = headers.GetValues("systemCode").First();
                    }
                    if (headers.Contains("appKey"))
                    {
                        appKey = headers.GetValues("appKey").First();
                    }
                    if (headers.Contains("timeSpan"))
                    {
                        timeSpan = headers.GetValues("timeSpan").First();
                    }
                    if (headers.Contains("signature"))
                    {
                        signature = headers.GetValues("signature").First();
                    }
                    if (headers.Contains("permissionCode"))
                    {
                        permissionCode = headers.GetValues("permissionCode").First();
                    }
                    if (headers.Contains("userInfoStr"))
                    {
                        userInfoStr = headers.GetValues("userInfoStr").First();
                        userInfo = BaseUserInfo.Deserialize(userInfoStr);
                    }
    
                    authenticationIdentity = new BasicAuthenticationIdentity(systemCode, appKey, timeSpan, signature, userInfo, permissionCode);
                    result.Status = true;
                    result.StatusCode = Status.OK.ToString();
                    result.StatusMessage = "构建成功";
                }
                catch (Exception ex)
                {
                    NLogHelper.Warn(ex, "ParseHeader");
                    result.Status = false;
                    result.StatusCode = Status.Error.ToString();
                    result.StatusMessage = "异常:" + ex.Message;
                }
    
                return authenticationIdentity;
            }
    
            /// <summary>
            /// 授权验证失败
            /// </summary>
            /// <param name="filterContext"></param>
            private static void ChallengeAuthRequest(HttpActionContext filterContext, BaseResult result)
            {
                var dnsHost = filterContext.Request.RequestUri.DnsSafeHost;
                //filterContext.Response = filterContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
                filterContext.Response = filterContext.Request.CreateResponse(HttpStatusCode.OK, result);
                filterContext.Response.Headers.Add("WWW-Authenticate", string.Format("Basic realm="{0}"", dnsHost));
            }
        }
    
        /// <summary>
        /// 认证实体类
        /// </summary>
        public class BasicAuthenticationIdentity : GenericIdentity
        {
            /// <summary>
            /// 系统编号
            /// </summary>
            public string SystemCode { get; set; }
    
            /// <summary>
            /// AppKey
            /// </summary>
            public string AppKey { get; set; }
    
            /// <summary>
            /// 请求时间戳
            /// </summary>
            public string TimeSpan { get; set; }
    
            /// <summary>
            /// Signature 签名值
            /// </summary>
            public string Signature { get; set; }
    
            /// <summary>
            /// 用户信息
            /// </summary>
            public BaseUserInfo UserInfo { get; set; }
    
            /// <summary>
            /// 权限编号
            /// </summary>
            public string PermissionCode { get; set; }
    
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="systemCode"></param>
            /// <param name="appKey"></param>
            /// <param name="timeSpan"></param>
            /// <param name="signature"></param>
            /// <param name="userInfo"></param>
            /// <param name="permissionCode"></param>
            public BasicAuthenticationIdentity(string systemCode, string appKey, string timeSpan, string signature, BaseUserInfo userInfo, string permissionCode)
                : base(appKey, "Basic")
            {
                this.SystemCode = systemCode;
                this.AppKey = appKey;
                this.TimeSpan = timeSpan;
                this.Signature = signature;
                this.UserInfo = userInfo;
                this.PermissionCode = permissionCode;
            }
        }
    }

    不需要做校验的接口,加一个标签

    //-----------------------------------------------------------------------
    // <copyright file="ApiAuthenticationFilter.cs" company="FenSiShengHuo, Ltd.">
    //     Copyright (c) 2018 , All rights reserved.
    // </copyright>
    //-----------------------------------------------------------------------
    
    using System.Web.Http.Filters;
    
    namespace DotNet.WeChat.API.Attribute
    {
        /// <summary>
        /// ApiNoAuthenticationFilter
        /// 不做授权检查
        /// 
        /// 2018-07-19 版本:1.0 JiShiYu 创建。    
        ///
        /// <author>
        ///        <name>JiShiYu</name>
        ///        <date>2018-07-19</date>
        /// </author> 
        /// </summary>
        public class ApiNoAuthenticationFilter : AuthorizationFilterAttribute
        { 
        }
    }

    全局校验,放在哪里,你懂的

        public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
    
    
    
    
                // 接口授权检查
                config.Filters.Add(new ApiAuthenticationFilter());
    
    
        }
    }
    

      

    测试效果

  • 相关阅读:
    SAP OPEN UI5 Step 8: Translatable Texts
    SAP OPEN UI5 Step7 JSON Model
    SAP OPEN UI5 Step6 Modules
    SAP OPEN UI5 Step5 Controllers
    SAP OPEN UI5 Step4 Xml View
    SAP OPEN UI5 Step3 Controls
    SAP OPEN UI5 Step2 Bootstrap
    SAP OPEN UI5 Step1 环境安装和hello world
    2021php最新composer的使用攻略
    Php使用gzdeflate和ZLIB_ENCODING_DEFLATE结果gzinflate报data error
  • 原文地址:https://www.cnblogs.com/hnsongbiao/p/9381862.html
Copyright © 2011-2022 走看看