通过网上查看相关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(, , )); // 当地时区
DateTime dtStart = startTime.AddSeconds(unixTimeStamp);
TimeSpan ts = DateTime.Now - dtStart;
if (ts.TotalMinutes > )
{
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, , , 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()); }
}

  

测试效果

WebAPI接口安全校验的更多相关文章

  1. WebApi接口访问异常问题。尝试创建“testController”类型的控制器时出错。请确保控制器具有无参数公共构造函数

    本来运行的好好的webAPI 接口突然报了个 :“尝试创建“testController”类型的控制器时出错.请确保控制器具有无参数公共构造函数” 错误.耗了半宿最终解决了, 原因: api控制器中引 ...

  2. WebApi接口 - 如何在应用中调用webapi接口

    很高兴能再次和大家分享webapi接口的相关文章,本篇将要讲解的是如何在应用中调用webapi接口:对于大部分做内部管理系统及类似系统的朋友来说很少会去调用别人的接口,因此可能在这方面存在一些困惑,希 ...

  3. C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解

    前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.之前分享过一篇 C#进阶系列——WebApi接口传参不再困惑:传参详解  ...

  4. C#进阶系列——WebApi 接口参数不再困惑:传参详解

    前言:还记得刚使用WebApi那会儿,被它的传参机制折腾了好久,查阅了半天资料.如今,使用WebApi也有段时间了,今天就记录下API接口传参的一些方式方法,算是一个笔记,也希望能帮初学者少走弯路.本 ...

  5. ASP.NET MVC对WebAPI接口操作(添加,更新和删除)

    昨天<怎样操作WebAPI接口(显示数据)>http://www.cnblogs.com/insus/p/5670401.html 既有使用jQuery,也有使作HttpClient来从数 ...

  6. WebApi 接口参数不再困惑:传参详解

    阅读目录 一.get请求 1.基础类型参数 2.实体作为参数 3.数组作为参数 4.“怪异”的get请求 二.post请求 1.基础类型参数 2.实体作为参数 3.数组作为参数 4.后台发送请求参数的 ...

  7. 利用委托与Lambada创建和调用webapi接口

    前言 现在项目中用的是webapi,其中有以下问题:    1.接口随着开发的增多逐渐增加相当庞大. 2.接口调用时不好管理. 以上是主要问题,对此就衍生了一个想法: 如果每一个接口都一个配置文件来管 ...

  8. 【转】C#进阶系列——WebApi 接口参数不再困惑:传参详解

    原文地址:http://www.cnblogs.com/landeanfen/archive/2016/04/06/5337072.html 阅读目录 一.get请求 1.基础类型参数 2.实体作为参 ...

  9. WebAPI接口测试之matthewcv.WebApiTestClient

    WebAPI接口测试之matthewcv.WebApiTestClient matthewcv.WebApiTestClient 1.安装matthewcv.WebApiTestClient包 打开v ...

随机推荐

  1. C# Note30: 网络爬虫

    用C#实现网络爬虫(一) 用C#实现网络爬虫(二) 基于C#.NET的高端智能化网络爬虫(一)(反爬虫哥必看) 基于C#.NET的高端智能化网络爬虫(二)(攻破携程网) C#获取网页内容的三种方式

  2. linux audit审计(5)--audit规则配置

    audit可以配置规则,这个规则主要是给内核模块下发的,内核audit模块会按照这个规则获取审计信息,发送给auditd来记录日志. 规则类型可分为: 1.控制规则:控制audit系统的规则: 2.文 ...

  3. vue element-ui 绑定@keyup事件无效

    解决办法: <el-input @keyup.native="ajax"></el-input> 加上.native覆盖原有封装的keyup事件即可

  4. JAVA锁机制-可重入锁,可中断锁,公平锁,读写锁,自旋锁,

    如果需要查看具体的synchronized和lock的实现原理,请参考:解决多线程安全问题-无非两个方法synchronized和lock 具体原理(百度) 在并发编程中,经常遇到多个线程访问同一个 ...

  5. 刪除nodejs

    https://www.cnblogs.com/fighxp/p/7410235.html https://www.cnblogs.com/fighxp/p/7411608.html

  6. java.lang.Exception: No tests found matching [{ExactMatcher:fDisplayName=fun2], {ExactMatcher:fDisplayName=fun2(cn.itcast.demo2.fun1)], {LeadingIdentifierMatcher:fClassName=cn.itcast.demo2.fun1,fLeadi

    Junit报的错误, 在测试方法前面没有添加注解@Test

  7. react用class关键字来创建组件

    创建组件之前,首先学习一个ES6的写法,叫做展开运算符. 比如我这里有两个数组.如何将第二个数组o2中的所有属性导入到数组o1中呢?一个个输太麻烦,所以就用到了展开运算符. var o2={ age: ...

  8. model,map,MapAndVivew用于页面跳转时候使用的即跳转后才添加属性 这样再回调中无法使用 因为回调的前提是页面不调转;解决的方法是用responsewrite(普通的字符响应)

    model,map,MapAndVivew用于页面跳转时候使用的即跳转后才添加属性 这样再回调中无法使用 因为回调的前提是页面不调转:解决的方法是用responsewrite

  9. hdu-6166(最短路+二进制分组)

    题意:给你n个点m条边的有向图,然后再给你k个不同的点,问你这k个点的最小距离: 解题思路:这道题最需要注意的就是k个点一定是不同的,那么有一个结论就是任意两个不同的数字中,在他们的二进制地表示中,一 ...

  10. 前端es6基础语法

    1.let.const.var var是声明全局的变量,作用域是全局,const是声明全局的常量,不能修改,而let是块级变量只在当前声明的作用域中生效: { var a = 10; let b = ...