过滤器实现Token验证(登录验证+过期验证)---简单的实现
功能:登录验证+过期验证+注销清除cookie+未注销下关闭或刷新浏览器仍可直接访问action
概述:token只存在客户端cookie,后端AES加密+解密+验证,每一次成功访问action都会刷新token包括过期时间
1.过滤器
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Mvc;
namespace TokenTest.MyActionFilter
{
/// <summary>
/// <param name="Die_Time">Die_Time//设置token过期时间小于7days</param>
/// <param name="Jump_Page">Jump_Page//设置token验证失败后跳转页面如/Login/Index;可携带参数/Login/Index?******</param>
/// </summary>
public class Token_Filter:ActionFilterAttribute//继承ActionFilterAttribute类
{
public int Die_Time { get; set;}//设置token过期时间<7days
public string Jump_Page { get; set; }//设置token验证失败后跳转页面如/Login/Index;可携带参数/Login/Index?******
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var token = HttpContext.Current.Request.Cookies["Token"];
if (token==null)
{
HttpContext.Current.Response.Write("<script language='javascript'>alert('您未登陆,请先登陆!');location.href='" + Jump_Page + "' ;</script>");
}
else
{
string U_ID = AESDecrypt(token.Value.ToString(), "jjq").Split('_')[0];
DateTime Token_Time = Convert.ToDateTime(AESDecrypt(token.Value.ToString(), "jjq").Split('_')[1]);
//检验过期时间;token理论上验证有效期:Die_Time<7天/////每次加载过滤action都会重新设置时间(可改)
if (Token_Time.AddDays(Die_Time) < DateTime.Now)
{
HttpContext.Current.Response.Write("<script language='javascript'>alert('登陆过期,请重新登录!');location.href='" + Jump_Page + "' ;</script>");
}
else
{
//完全验证通过后重新改写token并覆写在cookie里
Set_Token(U_ID);
}
}
}
public static void Set_Token(string user_name)
{
var Token = AESEncrypt(user_name + "_" + DateTime.Now.ToString() + "_" + Guid.NewGuid(), "jjq");//Token加密;;jjq加密密匙
HttpContext.Current.Response.Cookies["Token"].Value = Token;
HttpContext.Current.Response.Cookies["Token"].Expires = DateTime.Now.AddDays(7);//设置Token客户端保留时间7天
}
#region
/// <summary>
/// 加密解密功能代码片段
/// </summary>
//AES密钥向量
private static readonly byte[] _aeskeys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
/// <summary>
/// AES加密
/// </summary>
/// <param name="encryptStr">加密字符串</param>
/// <param name="encryptKey">密钥</param>
/// <returns></returns>
public static string AESEncrypt(string encryptStr, string encryptKey)
{
if (string.IsNullOrWhiteSpace(encryptStr))
return string.Empty;
encryptKey = SubString(encryptKey, 0, 32);
encryptKey = encryptKey.PadRight(32, ' ');
//分组加密算法
SymmetricAlgorithm des = Rijndael.Create();
byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptStr);//得到需要加密的字节数组
//设置密钥及密钥向量
des.Key = Encoding.UTF8.GetBytes(encryptKey);
des.IV = _aeskeys;
byte[] cipherBytes = null;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
cipherBytes = ms.ToArray();//得到加密后的字节数组
cs.Close();
ms.Close();
}
}
return Convert.ToBase64String(cipherBytes);
}
/// <summary>
/// AES解密
/// </summary>
/// <param name="decryptStr">解密字符串</param>
/// <param name="decryptKey">密钥</param>
/// <returns></returns>
public static string AESDecrypt(string decryptStr, string decryptKey)
{
if (string.IsNullOrWhiteSpace(decryptStr))
return string.Empty;
decryptKey = SubString(decryptKey, 0, 32);
decryptKey = decryptKey.PadRight(32, ' ');
byte[] cipherText = Convert.FromBase64String(decryptStr);
SymmetricAlgorithm des = Rijndael.Create();
des.Key = Encoding.UTF8.GetBytes(decryptKey);
des.IV = _aeskeys;
byte[] decryptBytes = new byte[cipherText.Length];
using (MemoryStream ms = new MemoryStream(cipherText))
{
using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read))
{
cs.Read(decryptBytes, 0, decryptBytes.Length);
cs.Close();
ms.Close();
}
}
return Encoding.UTF8.GetString(decryptBytes).Replace("\0", "");//将字符串后尾的'\0'去掉
}
public static string SubString(string sourceStr, int startIndex, int length)
{
if (!string.IsNullOrEmpty(sourceStr))
{
if (sourceStr.Length >= (startIndex + length))
return sourceStr.Substring(startIndex, length);
else
return sourceStr.Substring(startIndex);
}
return "";
}
#endregion
}
}
2.使用方法
1.需要过滤的Controller中引用(注意给参数)
using System.Web.Mvc;
using TokenTest.MyActionFilter;
namespace TokenTest.Controllers
{
public class adminController : Controller
{
// GET: admin
[Token_Filter(Die_Time=3,Jump_Page = "/Login/Index")]
public ActionResult Index()
{
return View();
}
}
}
2.LoginController中引用Token_Filter.Set_Token()方法;激活设置token+注销按钮(清除cookie)
using System;
using System.Web.Mvc;
using TokenTest.MyActionFilter;
namespace TokenTest.Controllers
{/// <summary>
/// ////////////////////////////////////////////////
/// </summary>
public class LoginController : Controller
{
// GET: Login
public ActionResult Index()
{
return View();
}
public ActionResult Logout()
{
//注销按钮---清除cookie
Response.Cookies["Token"].Expires = DateTime.Now.AddDays(-1);
return View("Index");
}
public ActionResult Login()
{
var get_name = Request["name"];
var get_pwd = Request["pwd"];
JJQPractice visitor = JJQPractice.SingleOrDefault(new { name = get_name });//得到对应输入的账号的集
if (visitor != null)//验证输入的账号是否存在
{
if (visitor.pwd == get_pwd)//验证密码是否正确
{
Token_Filter.Set_Token(get_name);
return RedirectToAction("Index", "admin"); //密码正确后跳转到查询视图
}
else
{
Response.Write("登录失败!密码错误.");
return View("Index");
}
}
else
{
Response.Write("登录失败,用户名不存在.");
return View("Index");
}
}
}
}
<h2>Logn-Index</h2>
<br><br>
<form action="/Login/Login" method="post">
姓名:<input type="text" name="name"/><br><br>
密码:<input type="text" name="pwd"/><br><br>
<input type="submit" value="提交"/><br><br>
</form>
<h2>Index</h2>
<form action="/admin/Index" method="post">
<input name="h" value="6666"/>
<input type="submit" value="按钮"/><br /><br />
</form>
<form action="/Login/Logout" method="post">
<input type="submit" value="注销_清除cookie" />
</form>
过滤器实现Token验证(登录验证+过期验证)---简单的实现的更多相关文章
- MVC 自定义过滤器/特性来实现登录授权及验证
最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精 最近在做自学MVC,遇到的问题很多,索性一点点总结 ...
- SpringBoot实现基于token的登录验证
一.SpringBoot实现基于token的登录验证 基于token的登录验证实现原理:客户端通过用户名和密码调用登录接口,当验证数据库中存在该用户后,将用户的信息按照token的生成规则,生成一个字 ...
- Java实现token的生成与验证-登录功能
一.token与cookie相比较的优势1.支持跨域访问,将token置于请求头中,而cookie是不支持跨域访问的: 2.无状态化,服务端无需存储token,只需要验证token信息是否正确即可,而 ...
- app与php后台接口登录认证、验证(seesion和token)
简要:随着电商的不断发展,APP也层次不穷,随着科技的发展主要登录形式(微信.QQ.账号/密码):为此向大家分享一下"app与php后台接口登录认证.验证"想法和做法:希望能够帮助 ...
- [更新]一份包含: 采用RSA JWT(Json Web Token, RSA加密)的OAUTH2.0,HTTP BASIC,本地数据库验证,Windows域验证,单点登录的Spring Security配置文件
没有任何注释,表怪我(¬_¬) 更新: 2016.05.29: 将AuthorizationServer和ResourceServer分开配置 2016.05.29: Token获取采用Http Ba ...
- jwt验证登录信息
为什么要告别session?有这样一个场景,系统的数据量达到千万级,需要几台服务器部署,当一个用户在其中一台服务器登录后,用session保存其登录信息,其他服务器怎么知道该用户登录了?(单点登录), ...
- Python Django缓存,信号,序列化,文件上传,Ajax登录和csrf_token验证
本节内容 models操作 Django的缓存 请求方式 序列化 Form 配合Ajax实现登录认证 上传文件 Ajax csrf_token验证方式 1 models操作 单表查询: curd(增 ...
- vue拦截器实现统一token,并兼容IE9验证
项目中使用vue搭建前端页面,并通过axios请求后台api接口,完成数据交互.如果验证口令token写在在每次的接口中,也是个不小的体力活,而且也不灵活.这里分享使用vue自带拦截器,给每次请求的头 ...
- [置顶] Web用户的身份验证及WebApi权限验证流程的设计和实现 (不是Token驗證!!!不是Token驗證!!!都是基於用户身份的票据信息驗證!!!)
转发 http://blog.csdn.net/besley/article/details/8516894 不是Token驗證!!!不是Token驗證!!!都是基於用户身份的票据信息驗證!!! [ ...
随机推荐
- Java算法 -- 桶排序
桶排序(Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶里.每个桶再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序).桶排序是鸽巢排序 ...
- Servlet2.5版本和Servlet3.0版本
在学习这节之前你需要在你自己的电脑进行如下配置: 配置Java运行环境:JDK+JRE的安装配置,参考博客Windows下配置Java开发环境: 安装Eclipse:参考博客Windows下配置Jav ...
- WebViewJavascriptBridge js跟app的交互框架
https://github.com/marcuswestin/WebViewJavascriptBridge 参考: https://www.cnblogs.com/LiLihongqiang/p/ ...
- PCL贪婪投影三角化算法
贪婪投影三角化算法是一种对原始点云进行快速三角化的算法,该算法假设曲面光滑,点云密度变化均匀,不能在三角化的同时对曲面进行平滑和孔洞修复. 方法: (1)将三维点通过法线投影到某一平面 (2)对投影得 ...
- Spring boot使用Aspose.Slides操作ppt转PDF、转图片
最近要将ppt转为PDF和图片,Apache poi ,jacob都试了下 Apache poi 转图片乱码,处理了,还会存在部分乱码 jacob对系统依赖比较大,必须是windows还得安装MS O ...
- H2数据库介绍
H2数据库是一个开源的关系型数据库. H2是一个采用java语言编写的嵌入式数据库引擎,只是一个类库(即只有一个 jar 文件),可以直接嵌入到应用项目中,不受平台的限制 应用场景: 可以同应用程序打 ...
- filter和map内置函数
filter filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回 ...
- 谷歌浏览器调试javascript方法
谷歌浏览器调试javascript方法 1 ctrl + shift + f 全局文件搜索 然后加断点 也可以直接编辑js文件 保存后 就更新了 一般用在点击事件上 ps:如果加了断点 刷新浏览断点消 ...
- LeetCode 201. 数字范围按位与(Bitwise AND of Numbers Range)
201. 数字范围按位与 201. Bitwise AND of Numbers Range 题目描述 给定范围 [m, n],其中 0 <= m <= n <= 214748364 ...
- Spring Boot之从Spring Framework装配掌握SpringBoot自动装配
Spring Framework模式注解 模式注解是一种用于声明在应用中扮演“组件”角色的注解.如 Spring Framework 中的 @Repository 标注在任何类上 ,用于扮演仓储角色的 ...