webApi签名验证
还是一如既往先上结构图如下:

上一讲说明了redis,也谢谢心态的建议。这里经过改进后的redis的地址

当然这里是加密了的,具体实现如下图:

这里提供的解密。
先把加密解密的帮助类放上来。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks; namespace KuRuMi.Mio.DoMain.Infrastructure.Common
{
/// <summary>
/// 对称加密帮助类
/// </summary>
public class CryptographyExtension
{
// 对称加密算法提供器
private ICryptoTransform encryptor; // 加密器对象
private ICryptoTransform decryptor; // 解密器对象
private const int BufferSize = ;
private static string dataKey = "XXXXXXXX"; public CryptographyExtension(string algorithmName, string key)
{
SymmetricAlgorithm provider = SymmetricAlgorithm.Create(algorithmName);
provider.Key = Encoding.UTF8.GetBytes(key);
provider.IV = new byte[] { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; encryptor = provider.CreateEncryptor();
decryptor = provider.CreateDecryptor();
} public CryptographyExtension(string key) : this("TripleDES", key) { } /// <summary>
/// 加密算法
/// </summary>
/// <param name="clearText"></param>
/// <returns></returns>
public string Encrypt(string clearText)
{
// 创建明文流
byte[] clearBuffer = Encoding.UTF8.GetBytes(clearText);
MemoryStream clearStream = new MemoryStream(clearBuffer); // 创建空的密文流
MemoryStream encryptedStream = new MemoryStream(); CryptoStream cryptoStream =
new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write); // 将明文流写入到buffer中
// 将buffer中的数据写入到cryptoStream中
int bytesRead = ;
byte[] buffer = new byte[BufferSize];
do
{
bytesRead = clearStream.Read(buffer, , BufferSize);
cryptoStream.Write(buffer, , bytesRead);
} while (bytesRead > ); cryptoStream.FlushFinalBlock(); // 获取加密后的文本
buffer = encryptedStream.ToArray();
string encryptedText = Convert.ToBase64String(buffer);
return encryptedText;
} /// <summary>
/// 解密算法
/// </summary>
/// <param name="encryptedText"></param>
/// <returns></returns>
public string Decrypt(string encryptedText)
{
byte[] encryptedBuffer = Convert.FromBase64String(encryptedText);
Stream encryptedStream = new MemoryStream(encryptedBuffer); MemoryStream clearStream = new MemoryStream();
CryptoStream cryptoStream =
new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read); int bytesRead = ;
byte[] buffer = new byte[BufferSize]; do
{
bytesRead = cryptoStream.Read(buffer, , BufferSize);
clearStream.Write(buffer, , bytesRead);
} while (bytesRead > ); buffer = clearStream.GetBuffer();
string clearText =
Encoding.UTF8.GetString(buffer, , (int)clearStream.Length); return clearText;
} /// <summary>
/// 加密
/// </summary>
/// <param name="clearText"></param>
/// <param name="key"></param>
/// <returns></returns>
public static string Encrypts(string clearText)
{
CryptographyExtension helper = new CryptographyExtension(dataKey);
return helper.Encrypt(clearText);
} /// <summary>
/// 解密
/// </summary>
/// <param name="encryptedText"></param>
/// <param name="key"></param>
/// <returns></returns>
public static string Decrypts(string encryptedText)
{
CryptographyExtension helper = new CryptographyExtension(dataKey);
return helper.Decrypt(encryptedText);
}
}
}
完成这一些后,下面来看看签名验证。本来是写好了token+签名的验证,因为token目前还有些问题后来删掉了,改用签名验证。

这个方法是放在client端返回加密后的key。因为博主的项目全是post请求,这里就没有补充get请求。
public static T Post<T>(string url, string data, string appid)
{
byte[] bytes = Encoding.UTF8.GetBytes(data);
HttpWebRequest request = WebRequest.CreateHttp(url) as HttpWebRequest;
//加入到头信息中
request.Headers.Add("appid", appid);//当前的用户的请求id
request.Headers.Add("sign", GetSignature());//签名验证 //写数据
request.Method = "POST";
request.ContentLength = bytes.Length;
request.ContentType = "application/json";
Stream reqstream = request.GetRequestStream();
reqstream.Write(bytes, , bytes.Length); //读数据
request.Timeout = ;
request.Headers.Set("Pragma", "no-cache");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream streamReceive = response.GetResponseStream();
StreamReader streamReader = new StreamReader(streamReceive, Encoding.UTF8);
string strResult = streamReader.ReadToEnd(); //关闭流
reqstream.Close();
streamReader.Close();
streamReceive.Close();
request.Abort();
response.Close(); return JsonConvert.DeserializeObject<T>(strResult);
}
然后是调用:

页面上的写法就是在ajax里面加入请求头
$(function () {
$("#regist").click(function () {
var data = { userName: $("#text_r").val(), email: $("#email_r").val(), passWord: $("#password_r").val() };
debugger;
$.ajax({
//"Content-Type":"application/ json" //这里如果将此放入到headers里面会出现传入DTO参数的时候为空
headers: { appid: "2xl7w0Doqog=", sign: "MwOMp5bATVf1N2qNmAxW1GL1mduieOjsLHe45frBuISIpRE9OWncZ569sZraRQnwmWuQHNmJZJjCT/FaWsSiZw=="},
type: 'post',
datatype: 'json',
data: data,
url: 'http://localhost:13292/Api/App/DataForAjax',
success: function (data) {
$('small').html(data);
$('small').delay(3000).hide(0);
}
});
});
//"Content-Type":"application/ json" //这里如果将此放入到headers里面会出现传入DTO参数的时候为空
这里就是加上了
Content-Type":"application/ json造成的
去掉了之后

下面是filter代码
using KuRuMi.Mio.AppService.Common;
using KuRuMi.Mio.AppService.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters; namespace KuRuMi.Mio.AppService.Filter
{
public class SignSecretFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
ResultMsg resultMsg = null;
string appId = string.Empty;
string sign = string.Empty;
if (actionContext.Request.Headers.Contains("appid"))
{
appId = HttpUtility.UrlDecode(actionContext.Request.Headers.GetValues("appid").FirstOrDefault());
}
if (actionContext.Request.Headers.Contains("sign"))
{
sign = HttpUtility.UrlDecode(actionContext.Request.Headers.GetValues("sign").FirstOrDefault());
} //判断请求头是否包含以下参数
if (string.IsNullOrEmpty(appId) || string.IsNullOrEmpty(sign))
{
resultMsg = new ResultMsg();
resultMsg.StatusCode = (int)StatusCodeEnum.ParameterError;
resultMsg.Info = StatusCodeEnum.ParameterError.GetEnumText();
resultMsg.Data = "";
actionContext.Response = HttpResponseExtension.toJson(JsonConvert.SerializeObject(resultMsg));
base.OnActionExecuting(actionContext);
return;
}
//验证签名算法
bool result = SignExtension.Validate(appId, sign);
if (!result)
{
resultMsg = new ResultMsg();
resultMsg.StatusCode = (int)StatusCodeEnum.HttpRequestError;
resultMsg.Info = StatusCodeEnum.HttpRequestError.GetEnumText();
resultMsg.Data = "";
actionContext.Response = HttpResponseExtension.toJson(JsonConvert.SerializeObject(resultMsg));
base.OnActionExecuting(actionContext);
return;
}
}
}
}
服务器端验证签名的方法:
using KuRuMi.Mio.DoMain.Infrastructure.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web; namespace KuRuMi.Mio.AppService.Common
{
/// <summary>
/// 判断签名算法
/// </summary>
public class SignExtension
{
private static readonly string keys = "Kurumi";
/// <summary>
/// 判断签名算法
/// </summary>
/// <param name="appId"></param>
/// <param name="url"></param>
/// <param name="sign">签名</param>
/// <returns></returns>
public static bool Validate(string appId, string sign)
{
byte[] bytes = Encoding.UTF8.GetBytes(ConfigManagerExtension.SecretKey);
string signs = string.Empty;
if (appId != "")
signs = CryptographyExtension.Decrypts(appId) + keys;
else
signs = appId + keys;
byte[] val = Encoding.UTF8.GetBytes(string.Concat(signs.OrderBy(c => c)));//排序
string key = null;
using (HMACSHA512 SecretKey = new HMACSHA512(bytes))
{
var SecretKeyBytes = SecretKey.ComputeHash(val);
key = Convert.ToBase64String(SecretKeyBytes);
}
return (sign.Equals(key, StringComparison.Ordinal));
}
}
}
webApi签名验证的更多相关文章
- WebApi安全性 使用TOKEN+签名验证
首先问大家一个问题,你在写开放的API接口时是如何保证数据的安全性的?先来看看有哪些安全性问题在开放的api接口中,我们通过http Post或者Get方式请求服务器的时候,会面临着许多的安全性问题, ...
- WebAPI 安全性 使用TOKEN+签名验证(上)
首先问大家一个问题,你在写开放的API接口时是如何保证数据的安全性的?先来看看有哪些安全性问题在开放的api接口中,我们通过http Post或者Get方式请求服务器的时候,会面临着许多的安全性问题, ...
- WebAPI 用户认证防篡改实现HMAC(二)签名验证 AbsBaseAuthenticationAttribute--转
public class ActionFilter : ActionFilterAttribute { public override void OnActionExecu ...
- WebApi安全性 使用TOKEN+签名验证 (秘钥是GUID的,私有的,不是雙方的,并不在网络连接上传输)
转http://www.cnblogs.com/MR-YY/archive/2016/10/18/5972380.html WebApi安全性 使用TOKEN+签名验证 首先问大家一个问题,你在写 ...
- WebAPI 安全性 使用TOKEN+签名验证(下)
//根据请求类型拼接参数 NameValueCollection form = HttpContext.Current.Request.QueryString; string data = strin ...
- WebApi基于Token和签名的验证
最近一段时间在学习WebApi,涉及到验证部分的一些知识觉得自己并不是太懂,所以来博客园看了几篇博文,发现一篇讲的特别好的,读了几遍茅塞顿开(都闪开,我要装逼了),刚开始读有些地方不理解,所以想了很久 ...
- WebApi传参总动员(填坑)
本以为系列文章已经Over,突然记起来前面留了个大坑还没填,真是自己给自己挖坑. 这个坑就是: (body 只能被读取一次)Only one thing can read the body MVC和W ...
- TOKEN+签名验证
TOKEN+签名验证 首先问大家一个问题,你在写开放的API接口时是如何保证数据的安全性的?先来看看有哪些安全性问题在开放的api接口中,我们通过http Post或者Get方式请求服务器的时候,会面 ...
- 简析ASP.NET WebApi的跨域签名
之前的文章写了关于WebApi的跨域问题,当中的方法只是解决了简单请求的跨域问题而非简单请求的跨域问题则没有解决. 要弄清楚 CORS规范将哪些类型的跨域资源请求划分为简单请求的范畴,需要额外了解几个 ...
随机推荐
- 安装php提示 configure: error: Cannot find OpenSSL's libraries 解决方案
一次在安装php7其中提示错误信息 configure: error: Cannot find OpenSSL's libraries 出现这种有2中情况,一种是没有安装 openssl,另一种是安装 ...
- AspNetCore-MVC实战系列(三)之个人中心
AspNetCore - MVC实战系列目录 . 爱留图网站诞生 . git源码:https://github.com/shenniubuxing3/LovePicture.Web . AspNetC ...
- 浅析被element.style所覆盖的样式
近日,我在用swiper插件写一个手游官网时,出现了一个很奇怪的问题.问题如下 如上图所示,这里是一个可以左右拖动的ul,每一个英雄介绍都是一个li标签,上图这是正常的情况.可是,它会随机不定期不定时 ...
- Linux学习之要点必备
在本节课中我将会带领大家秒懂linux命令 要点一:常见基本命令格式 命令名称+选项+参数 例如:#mkdir -r /var/ruofeng/001/ 我们通过逐级创建目录方式解释这个例子,mkdi ...
- Nginx 反向代理&负载均衡
1.反向代理 当我们请求一个网站时,nginx会决定由哪台服务器提供服务,就是反向代理. nginx只做请求的转发,后台有多个tomcat服务器提供服务,nginx的功能就是把请求转发给后面的服务器, ...
- Android ViewPager动画切换
使用方法 setPageTransformer 例如: ViewPager.setPageTransformer(true, new ZoomOutPageTransformer()) package ...
- document.all 用法
一. document.all是页面内所有元素的一个集合.例如: document.all(0)表示页面内第一个元素 二. document.all可以判断浏览器是否是IE if ...
- linux优化之SElinux关闭
查看selinux状态: # getenforce 注:Enforcing表示开启,Permissive表示禁用 临时关闭或开启selinux: # setenforce [1|0] 注:1是 ...
- POJ1845-Sumdiv大数约数和
题目链接:http://poj.org/problem?id=1845 题目大意: 求A^B的所有约数和s.A和B都很大(0<=A,B<=50000000). 题目分析: 这道题让我学会了 ...
- Redis学习-SortedSet
Sorted-Sets和Sets类型极为相似,它们都是字符串的集合,都不允许重复的成员出现在一个Set中.它们之间的主要差别是Sorted-Sets中的每一个成员都会有一个分数(score)与之关联, ...
