功能:登录验证+过期验证+注销清除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验证(登录验证+过期验证)---简单的实现的更多相关文章

  1. MVC 自定义过滤器/特性来实现登录授权及验证

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精    最近在做自学MVC,遇到的问题很多,索性一点点总结 ...

  2. SpringBoot实现基于token的登录验证

    一.SpringBoot实现基于token的登录验证 基于token的登录验证实现原理:客户端通过用户名和密码调用登录接口,当验证数据库中存在该用户后,将用户的信息按照token的生成规则,生成一个字 ...

  3. Java实现token的生成与验证-登录功能

    一.token与cookie相比较的优势1.支持跨域访问,将token置于请求头中,而cookie是不支持跨域访问的: 2.无状态化,服务端无需存储token,只需要验证token信息是否正确即可,而 ...

  4. app与php后台接口登录认证、验证(seesion和token)

    简要:随着电商的不断发展,APP也层次不穷,随着科技的发展主要登录形式(微信.QQ.账号/密码):为此向大家分享一下"app与php后台接口登录认证.验证"想法和做法:希望能够帮助 ...

  5. [更新]一份包含: 采用RSA JWT(Json Web Token, RSA加密)的OAUTH2.0,HTTP BASIC,本地数据库验证,Windows域验证,单点登录的Spring Security配置文件

    没有任何注释,表怪我(¬_¬) 更新: 2016.05.29: 将AuthorizationServer和ResourceServer分开配置 2016.05.29: Token获取采用Http Ba ...

  6. jwt验证登录信息

    为什么要告别session?有这样一个场景,系统的数据量达到千万级,需要几台服务器部署,当一个用户在其中一台服务器登录后,用session保存其登录信息,其他服务器怎么知道该用户登录了?(单点登录), ...

  7. Python Django缓存,信号,序列化,文件上传,Ajax登录和csrf_token验证

    本节内容 models操作 Django的缓存 请求方式 序列化 Form 配合Ajax实现登录认证 上传文件 Ajax  csrf_token验证方式 1 models操作 单表查询: curd(增 ...

  8. vue拦截器实现统一token,并兼容IE9验证

    项目中使用vue搭建前端页面,并通过axios请求后台api接口,完成数据交互.如果验证口令token写在在每次的接口中,也是个不小的体力活,而且也不灵活.这里分享使用vue自带拦截器,给每次请求的头 ...

  9. [置顶] Web用户的身份验证及WebApi权限验证流程的设计和实现 (不是Token驗證!!!不是Token驗證!!!都是基於用户身份的票据信息驗證!!!)

     转发 http://blog.csdn.net/besley/article/details/8516894 不是Token驗證!!!不是Token驗證!!!都是基於用户身份的票据信息驗證!!! [ ...

随机推荐

  1. go-micro框架学习1-准备工作

    下载golang环境,地址:https://studygolang.com/dl,这里使用的是1.11.10版本. 下载golang IDE,这里使用Lite,下载地址:http://liteide. ...

  2. osg指定向量旋转指定角度

    向量AB,沿着n旋转10度 osg::Vec3 left = AB*osg::Matrix::rotate(osg::inDegrees(10), n); osg::Vec3 right = AB*o ...

  3. Gson字符串编码,字符串转换成图片保存,二进制转换成图片保存

    import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.File; import ...

  4. BladeX 2.0.7.RELEASE版本git后,在idea中导入项目,结果无法运行FlowApplication等几个服务的错误

    问题:2.0.7.RELEASE版本git后,在Intellij IDEA运行项目,结果无法运行FlowApplication等几个服务的错误 描述:打开IDEA,点击Check out from V ...

  5. linux广播

    linux广播 // 发送端 #include <stdio.h> #include <unistd.h> #include <sys/types.h> #incl ...

  6. sigaction和实时信号sigqueue

    sigaction函数sigaction函数的功能是用于改变进程接收到特定信号后的行为.int sigaction(int signum, const struct sigaction *act,st ...

  7. QT笔记--checkbox

    1 复选框 一般用来表示“是/否”.: 2 属性有哪些 如果需要默认选中,那么设置QAbstractButton->checked 3 哪些操作函数 需要判断是否选中.也就是isChecked( ...

  8. 基于thinkphp5框架做一个可以区别开发、测试、生产三种环境的配置加载

    在日常的开发测试中我们经常会遇到本地开发和测试或者线上配置参数不同的场景,必要你要是使用一个三方的支付,它的本地测试和线上的key值或者账号存在不同.最基本的做法是本地用测试参数,提交到测试的时候再改 ...

  9. python实践项目六:正则表达式-强口令

    描述:写一个函数,它使用正则表达式,确保传入的口令字符串是强口令.强口令的定义是:长度不少于8 个字符,  同时包含大写和小写字符, 至少有一位数字. 代码: #!/usr/bin/python # ...

  10. /x86_64-linux-gnu/libSM.so: undefined reference to `uuid_generate@UUID_1.0'错误

    在编译PCL的时候总是报错,其他人都没问题 后来发现是我cmakePCL的时候,QT引用的是anaconda里的qt,把这个一改果然没问题了,耽误了一天时间. 感谢stack上这位老铁