MVC 统一验证Token demo
/// <summary>
/// 获取token
/// </summary>
/// <param name="staffId"></param>
/// <returns></returns>
public JsonResult GetToken(string staffId)
{
ResultMsg resultMsg = null; //判断参数是否合法
if (string.IsNullOrEmpty(staffId))
{
resultMsg = new ResultMsg();
resultMsg.StatusCode = (int)StatusCodeEnum.ParameterError;
resultMsg.Info = "staffId不合法";
resultMsg.Data = new Token();
return Json(resultMsg, JsonRequestBehavior.AllowGet);
} //插入缓存
Token token = (Token)HttpRuntime.Cache.Get(staffId);
if (HttpRuntime.Cache.Get(staffId.ToString()) == null)
{
token = new Token();
token.StaffId = staffId;
token.SignToken = Guid.NewGuid();
token.ExpireTime = DateTime.Now.AddDays();
HttpRuntime.Cache.Insert(token.StaffId.ToString(), token, null, token.ExpireTime, TimeSpan.Zero);
} //返回token信息
resultMsg = new ResultMsg();
resultMsg.StatusCode = (int)StatusCodeEnum.Success;
resultMsg.Info = "";
resultMsg.Data = token;
return Json(resultMsg, JsonRequestBehavior.AllowGet); }
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Mvc;
using WebApplication_Token.Models; namespace WebApplication_Token.Controllers
{
public class VerificationTokenController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
ResultMsg resultMsg = null;
var request = Request;
var method = request.HttpMethod;
string staffid = string.Empty, timestamp = string.Empty, nonce = string.Empty, signature = string.Empty; if (!string.IsNullOrEmpty(request.Headers["staffid"]))
{
staffid = HttpUtility.UrlDecode(request.Headers.GetValues("staffid").FirstOrDefault());
}
if (!string.IsNullOrEmpty(request.Headers["timestamp"]))
{
timestamp = HttpUtility.UrlDecode(request.Headers.GetValues("timestamp").FirstOrDefault());
}
if (!string.IsNullOrEmpty(request.Headers["nonce"]))
{
nonce = HttpUtility.UrlDecode(request.Headers.GetValues("nonce").FirstOrDefault());
}
if (!string.IsNullOrEmpty(request.Headers["signature"]))
{
signature = HttpUtility.UrlDecode(request.Headers.GetValues("signature").FirstOrDefault());
} //GetToken方法不需要进行签名验证
if (filterContext.ActionDescriptor.ActionName == "GetToken")
{
base.OnActionExecuting(filterContext);
return;
} //判断请求头是否包含以下参数
if (string.IsNullOrEmpty(staffid) || string.IsNullOrEmpty(timestamp) || string.IsNullOrEmpty(nonce) || string.IsNullOrEmpty(signature))
{
resultMsg = new ResultMsg();
resultMsg.StatusCode = (int)HttpStatusCode.PartialContent;
resultMsg.Info = "请求头缺少参数";
resultMsg.Data = new Token();
filterContext.Result = Json(resultMsg, JsonRequestBehavior.AllowGet);//返回json数据
base.OnActionExecuting(filterContext);
return;
} //判断token是否有效
Token token = (Token)HttpRuntime.Cache.Get(staffid); string signtoken = string.Empty;
if (token == null)
{
resultMsg = new ResultMsg();
resultMsg.StatusCode = (int)StatusCodeEnum.ParameterError;
resultMsg.Info = "token为null";
resultMsg.Data = new Token();
filterContext.Result = Json(resultMsg, JsonRequestBehavior.AllowGet);//返回json数据
base.OnActionExecuting(filterContext);
return;
}
else
{
signtoken = token.SignToken.ToString();
} bool timespanvalidate = token.ExpireTime > Convert.ToDateTime(timestamp);
if (!timespanvalidate)
{
resultMsg = new ResultMsg();
resultMsg.StatusCode = (int)HttpStatusCode.PartialContent;
resultMsg.Info = "token已过期";
resultMsg.Data = new Token();
filterContext.Result = Json(resultMsg, JsonRequestBehavior.AllowGet);//返回json数据
base.OnActionExecuting(filterContext);
return;
} //根据请求类型拼接参数
NameValueCollection coll = Request.Form;
string[] requestItem = coll.AllKeys;
Dictionary<string, string> sArray = new Dictionary<string, string>();
int j = ;
for (j = ; j < requestItem.Length; j++)
{
sArray.Add(requestItem[j], Request.Form[requestItem[j]]);
}
var queryStr = GetQueryString(sArray);
var _signature = GetSingnature(timestamp, queryStr.Item1, staffid, signtoken, queryStr.Item2); if(signature!= _signature)
{
resultMsg = new ResultMsg();
resultMsg.StatusCode = (int)HttpStatusCode.PartialContent;
resultMsg.Info = "token不合法";
resultMsg.Data = new Token();
filterContext.Result = Json(resultMsg, JsonRequestBehavior.AllowGet);//返回json数据
base.OnActionExecuting(filterContext);
return;
} } /// <summary>
/// 获取签名字符串
/// </summary>
/// <param name="parames"></param>
/// <returns></returns>
public Tuple<string, string> GetQueryString(Dictionary<string, string> parames)
{
// 第一步:把字典按Key的字母顺序排序
IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parames);
IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator(); // 第二步:把所有参数名和参数值串在一起
StringBuilder query = new StringBuilder("");//签名字符串
StringBuilder queryStr = new StringBuilder("");//url参数
if (parames == null || parames.Count == )
{
return new Tuple<string, string>("", "");
} while (dem.MoveNext())
{
string key = dem.Current.Key;
string value = dem.Current.Value;
if (!string.IsNullOrEmpty(key))
{
query.Append(key).Append(value);
queryStr.Append("&").Append(key).Append("=").Append(value);
}
} return new Tuple<string, string>(query.ToString(), queryStr.ToString().Substring(, queryStr.Length - ));
} /// <summary>
/// 根据参数计算签名
/// </summary>
/// <param name="timeStamp">发起请求时的时间戳(单位:毫秒)</param>
/// <param name="nonce">随机数</param>
/// <param name="staffId">当前请求用户StaffId</param>
/// <param name="signToken">signToken</param>
/// <param name="data">参数url</param>
/// <returns></returns>
public string GetSingnature(string timeStamp, string nonce, string staffId,string signToken, string data)
{
var hash = System.Security.Cryptography.MD5.Create();
//拼接签名
var signStr = timeStamp + nonce + staffId + signToken + data;
//将字符串中字符按升序排序
var sortStr = string.Concat(signStr.OrderBy(c => c));
var bytes = Encoding.UTF8.GetBytes(sortStr);
//使用MD5加密
var md5Val = hash.ComputeHash(bytes);
//把二进制转大写十六进制
StringBuilder result = new StringBuilder();
foreach (var c in md5Val)
{
result.Append(c.ToString("X2"));
}
return result.ToString().ToUpper(); }
}
}
MVC 统一验证Token demo的更多相关文章
- Spring Cloud中Feign如何统一设置验证token
代码地址:https://github.com/hbbliyong/springcloud.git 原理是通过每个微服务请求之前都从认证服务获取认证之后的token,然后将token放入到请求头中带过 ...
- 本版本延续MVC中的统一验证机制~续的这篇文章,本篇主要是对验证基类的扩展和改善(转)
本版本延续MVC中的统一验证机制~续的这篇文章,本篇主要是对验证基类的扩展和改善 namespace Web.Mvc.Extensions { #region 验证基类 /// <summary ...
- .NET Core微服务之基于Ocelot+IdentityServer实现统一验证与授权
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.案例结构总览 这里,假设我们有两个客户端(一个Web网站,一个移动App),他们要使用系统,需要通过API网关(这里API网关始终作为 ...
- 使用Spring MVC统一异常处理实战
1 描述 在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的.不可预知的异常需要处理.每个过程都单独处理异常,系统的代码耦合 ...
- 使用Spring MVC统一异常处理实战<转>
1 描述 在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的.不可预知的异常需要处理.每个过程都单独处理异常,系统的代码耦合 ...
- MVC 数据验证
MVC 数据验证 前一篇说了MVC数据验证的例子,这次来详细说说各种各样的验证注解.System.ComponentModel.DataAnnotations 一.基础特性 一.Required 必填 ...
- MVC 数据验证[转]
前一篇说了MVC数据验证的例子,这次来详细说说各种各样的验证注解. 一.基础特性 一.Required 必填选项,当提交的表单缺少该值就引发验证错误. 二.StringLength 指定允许的长度 指 ...
- NET MVC权限验证
ASP.NET MVC权限验证 封装类 写该权限类主要目地 为了让权限配置更加的灵活,可以根据SQL.json.或者XML的方式来动态进行页面的访问控制,以及没有权限的相关跳转. 使用步骤 1.要建一 ...
- Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务、WCF消息头添加安全验证Token
原文:Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务.WCF消息头添加安全验证Token 为什么选择wcf? 因为好像wcf和wpf就是哥俩,,, 为什么选择异步 ...
随机推荐
- PHP 内存管理及垃圾回收机制
PHP5的内存管理 对象传递 PHP5使用了Zend引擎II,对象被储存于独立的结构Object Store中,而不像其它一般变量那样储存于Zval中(在PHP4中对象和一般变量一样存储于Zval). ...
- 【t079】火星上的加法运算
Time Limit: 1 second Memory Limit: 128 MB [问题描述] 最近欢欢看到一本有关火星的书籍,其中她被一个加法运算所困惑,由于她的运算水平有限,想向你求助,作为一名 ...
- Windows Community Toolkit 3.0 新功能 在WinForms 和 WPF 使用 UWP 控件
本文告诉大家一个令人震惊的消息,Windows Community Toolkit 有一个大更新,现在的版本是 3.0 .最大的提升就是 WinForm 和 WPF 程序可以使用部分 UWP 控件. ...
- H3C 帧中继基本配置命令(续)
- The 10th Shandong Provincial Collegiate Programming Contest H.Tokens on the Segments(贪心+优先级队列 or 贪心+暴力)
传送门 •题意 二维平面上有 n 条线段,每条线段坐标为 $(l_i,i),(r_i,i)$: 平面上的每个整点坐标上都可以放置一枚硬币,但是要求任意两枚硬币的横坐标不相同: 问最多有多少条线段可以放 ...
- H3C FTP其他常用命令
- SpringBoot --web 应用开发之文件上传
原文出处: oKong 前言 上一章节,我们讲解了利用模版引擎实现前端页面渲染,从而实现动态网页的功能,同时也提出了兼容jsp项目的解决方案.既然开始讲解web开发了,我们就接着继续往web这个方向继 ...
- 2019-9-20-SharpDx-的代替项目
title author date CreateTime categories SharpDx 的代替项目 lindexi 2019-09-20 09:13:59 +0800 2019-09-20 0 ...
- js 中日期2013-08-30或2019-08-24 12:30:00 转换成时间戳,和2019-08-29T02:15:08.000+0000转化为2019-08-29T02:15:08
js 中日期2019-08-24 或2019-08-24 12:30:00 转换成时间戳 首先将它转成date日期类型,然后获取毫秒形式时间戳 let date=new Date("2019 ...
- Redis内存回收机制
为什么需要内存回收? 原因有如下两点: 在 Redis 中,Set 指令可以指定 Key 的过期时间,当过期时间到达以后,Key 就失效了. Redis 是基于内存操作的,所有的数据都是保存在内存中, ...