过滤器实现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驗證!!!都是基於用户身份的票据信息驗證!!! [ ...
随机推荐
- Could not get JDBC Connection; nested exception is java.sql.SQLException: ${jdbc.driver}
在一个SSM分布式项目中一个服务报错: ### Error querying database. Cause: org.springframework.jdbc.CannotGetJdbcConnec ...
- 不规则形状的Ifc构件顶点坐标获取
不规则形状的Ifc构件顶点坐标获取 今天有人问我,ifc构件的顶点坐标怎么获取,自己前年的时候写过类似的程序,但有点记不清了,最近一直用C++解析ifc,慎重起见,还是重新再写一次,java版本的获取 ...
- Android原生同步登录状态到H5网页避免二次登录
本文解决的问题是目前流行的 Android/IOS 原生应用内嵌 WebView 网页时,原生与H5页面登录状态的同步. 大多数混合开发应用的登录都是在原生页面中,这就牵扯到一个问题,如何把登录状态传 ...
- 使用Fiddler工具发送post请求(带有json数据)以及get请求(Header方式传参)
Fiddler工具是一个http协议调试代理工具,它可以帮助程序员测试或调试程序,辅助web开发. Fiddler工具可以发送向服务端发送特定的HTTP请求以及接受服务器回应的请求和数据,是web调试 ...
- [LeetCode] 203. Remove Linked List Elements 移除链表元素
Remove all elements from a linked list of integers that have value val. ExampleGiven: 1 --> 2 --& ...
- [LeetCode] 314. Binary Tree Vertical Order Traversal 二叉树的垂直遍历
Given a binary tree, return the vertical order traversal of its nodes' values. (ie, from top to bott ...
- 寄存器vs缓存vs硬盘
对于多核cpu来说(一个处理器cpu上有多个核),L1/L2是各个核独自的,L3是多个核共享的 如下配置:一个处理器cpu,六个核.处理器速度为2.2GHz即电流每秒钟可以振荡22亿次.二级缓存256 ...
- Rabbitmq消息积压清理
#!/bin/bash QUE=`rabbitmqctl list_queues messages_ready name durable|grep -v "^Listing" |g ...
- Jenkins运行python脚本出现 configparser.NoSectionError: No section: 'XXXXXX'
原来的代码如下: def get_test_config(tag, key, config="config.ini"): cf = configparser.ConfigParse ...
- LeetCode 445. 两数相加 II(Add Two Numbers II)
445. 两数相加 II 445. Add Two Numbers II 题目描述 给定两个非空链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储单个数字.将这两数相加会返回一个 ...