MVC5 一套Action的登录控制流程
流程:
用拦截器控制每一个页面请求和ajax请求,根据请求体的cookie里面是否有token判断是否登录,还必须判断该token在redis里面的缓存是否存在
组成部分:
拦截器:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using Rongzi.RZR.Huoke.Infrastructure.Util;
using Rongzi.RZR.Huoke.Entity;
using Rongzi.RZR.Huoke.Entity.Constants;
using Rongzi.RZR.Huoke.Infrastructure.Model;
using Rongzi.RZR.Huoke.Entity.Models; namespace Rongzi.RZR.Huoke.Infrastructure.Filter
{
public class ApiAuthFilterAttribute:System.Web.Mvc.ActionFilterAttribute
{
public bool isDoCheck { get; set; }
public ApiAuthFilterAttribute()
{
isDoCheck = true;
}
public ApiAuthFilterAttribute(bool isCheck = true)
{
isDoCheck = isCheck;
} public override void OnActionExecuting(ActionExecutingContext actionContext)
{
if (isDoCheck)
{ if (actionContext == null || actionContext.HttpContext.Request == null || actionContext.HttpContext.Request.RawUrl == null) { return; }
//string token = actionContext.HttpContext.Request.Headers["token"] ?? actionContext.HttpContext.Request.Cookies["token"].Value; string token = actionContext.HttpContext.Request.Cookies["token"]?.Value;
if (string.IsNullOrEmpty(token))
{
if (actionContext.HttpContext.Request.IsAjaxRequest())
{
actionContext.Result = GetAuthJsonResult();
}
else
{
actionContext.HttpContext.Response.Redirect("~/Account/Login");
}
return;
}
RedisOpearteResult redRes = TokenManager<OrganizationUser>.RefreshUserToken(token);
if (!redRes.isok)
{
if (actionContext.HttpContext.Request.IsAjaxRequest())
{
actionContext.Result = GetAuthJsonResult();
}
else
{
actionContext.HttpContext.Response.Redirect("~/Account/Login");
}
base.OnActionExecuting(actionContext);
return;
}
}
base.OnActionExecuting(actionContext);
} public static JsonResult GetAuthJsonResult()
{
var errResponse = new ResponseContext<string>();
errResponse.Head = new ResponseHead(-, ErrCode.AuthError, "用户还未登录");
return new JsonResult
{
Data = errResponse,
ContentEncoding = System.Text.Encoding.UTF8,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
} public override void OnActionExecuted(ActionExecutedContext actionExecutedContext)
{
base.OnActionExecuted(actionExecutedContext);
}
}
}
控制登录管理:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using Rongzi.RZR.Huoke.Entity.Models;
using Rongzi.RZR.Huoke.Infrastructure.Util;
using Rongzi.RZR.Huoke.Infrastructure.Model; namespace Rongzi.RZR.Huoke.Infrastructure
{
public class FormsAuth
{
///// <summary>
///// 生成Userdata
///// </summary>
///// <param name="user">用户model</param>
///// <returns></returns>
//private static string GenerateUserData(long userId, string userName, string userAccount, string imageUrl)
//{
// return string.Join("|", userId, userName, userAccount, imageUrl);
//} ///// <summary>
///// 登录系统
///// </summary>
///// <param name="user">用户model</param>
///// <param name="isRemember"是否记住></param>
///// <param name="days">超时时间</param>
//public static void SignIn(long userId, string userName, string userAccount, string imageUrl, bool isRemember, int days)
//{
// var userData = GenerateUserData(userId, userName, userAccount, imageUrl);
// var enyUserData = DEncrypt.Encrypt(userData);
// var ticket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddDays(days), isRemember, enyUserData);
// var enyTicket = FormsAuthentication.Encrypt(ticket); // var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, enyTicket); // HttpContext.Current.Response.Cookies.Add(authCookie);
//} /// <summary>
/// 登录系统
/// </summary>
/// <param name="user"></param>
public static void SignIn(OrganizationUser user)
{
RedisOpearteResult result = TokenManager<OrganizationUser>.getToken(user);
var authCookie = new HttpCookie("token", result.token);
HttpContext.Current.Response.SetCookie(authCookie); } /// <summary>
/// 退出系统
/// </summary>
/// <param name="token"></param>
public static void SignOff()
{
var cookie = HttpContext.Current.Request.Cookies["token"];
if (cookie != null)
{
string token = cookie.Value;
TokenManager<OrganizationUser>.LoginOff(token);
HttpContext.Current.Response.Cookies["token"].Expires = DateTime.Now.AddDays(-);
}
} public static OrganizationUser GetUserInfo()
{
var cookie = HttpContext.Current.Request.Cookies["token"];
if (cookie != null)
{
string token = cookie.Value;
return TokenManager<OrganizationUser>.getUserByToken(token);
}
return null;
}
}
}
TokenManager管理:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Rongzi.Cache.Redis;
using System.Configuration;
using Rongzi.RZR.Huoke.Infrastructure.Model; namespace Rongzi.RZR.Huoke.Infrastructure.Util
{
public class TokenManager<TUser>
{
/// <summary>
/// 设置对象过期时间
/// </summary>
private static readonly int interval = Convert.ToInt32(ConfigurationManager.AppSettings["Redis_UserExpire"]);
private static readonly string prefix = "OrganizationUser:"; /// <summary>
/// 存储对象val,获取对应的token
/// </summary>
/// <param name="val"></param>
/// <returns></returns>
public static RedisOpearteResult getToken(TUser val)
{
string tokenID = Guid.NewGuid().ToString();
RedisOpearteResult result = new RedisOpearteResult
{
isok = RedisCache.Add(prefix + tokenID, val, interval),
token = tokenID,
result = JsonConvert.SerializeObject(val)
};
return result;
} /// <summary>
/// 根据tokenID更新用户对象
/// </summary>
/// <param name="tokenID"></param>
/// <param name="val"></param>
/// <returns></returns>
public static RedisOpearteResult RefreshLoginTokenData(String tokenID, TUser val)
{
RedisOpearteResult result = new RedisOpearteResult
{
isok = RedisCache.Add(prefix + tokenID, val, interval),
token = tokenID,
result = JsonConvert.SerializeObject(val)
};
return result;
} /// <summary>
/// 刷新用户token
/// </summary>
/// <param name="tokenID"></param>
public static RedisOpearteResult RefreshUserToken(string tokenID)
{
var obj = RedisCache.Get<TUser>(prefix + tokenID);
var isExist = obj != null;
RedisOpearteResult result = new RedisOpearteResult
{
isok = isExist,
token = tokenID,
result = "Token过期"
};
if (isExist)
{
result.result = "成功延迟";
RedisCache.SetExpire(prefix + tokenID, new TimeSpan(, interval, ));
}
return result;
} /// <summary>
/// 退出
/// </summary>
/// <param name="tokenID"></param>
/// <returns></returns>
public static RedisOpearteResult LoginOff(string tokenID)
{
var obj = RedisCache.Get<TUser>(prefix + tokenID);
var isExist = obj != null;
RedisOpearteResult result = new RedisOpearteResult
{
isok = isExist,
token = tokenID,
result = "Token过期"
};
if (isExist)
{
result.result = "退出成功";
RedisCache.Remove(prefix + tokenID);
}
return result;
} /// <summary>
/// 通过token 获取用户信息
/// </summary>
/// <param name="token">tokenID</param>
/// <returns></returns>
public static TUser getUserByToken(string tokenID)
{
if (!string.IsNullOrEmpty(tokenID))
{
return RedisCache.Get<TUser>(prefix + tokenID);
}
return default(TUser);
}
}
}
其他:
public class RedisOpearteResult
{
public string token { get; set; }
public bool isok { get; set; }
public int code { get; set; }
public object data { get; set; }
public string result { get; set; } }
其实整个流程不难,下面说说坑:
Cookie的修改
登录时,不能使用
HttpContext.Current.Response.Cookies.Add(authCookie);
这个是不断的添加cookie,有相同路径的,就添加不同路径的
应该使用:
HttpContext.Current.Response.SetCookie(authCookie);
这个才是唯一性的,有就修改,没有就添加
Cookie的删除:
HttpContext.Current.Response.Cookies.Remove("token");
这个是旧的使用方式,发现怎么也没有用,浏览器中还是有这个cookie,后来查询资料,这个就对服务器中的cookies进行删除,但是并不对浏览器中的cookie进行操作。
应该使用过期时间:
HttpContext.Current.Response.Cookies["token"].Expires = DateTime.Now.AddDays(-);
还有一点,获取cookie的信息的时候使用Request的,不要使用Response的,发现对象存在,但是里面的值是空字符串
var cookie = HttpContext.Current.Request.Cookies["token"];
上面3个就是我踩的坑,以后注意!
MVC5 一套Action的登录控制流程的更多相关文章
- MySQL数据库学习笔记(四)----MySQL聚合函数、控制流程函数(含navicat软件的介绍)
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- MySQL聚合函数、控制流程函数(含navicat软件的介绍)
MySQL聚合函数.控制流程函数(含navicat软件的介绍) 一.navicat的引入:(第三方可视化的客户端,方便MySQL数据库的管理和维护) NavicatTM是一套快速.可靠并价格相宜的数据 ...
- WebAPI 用ActionFilterAttribute实现token令牌验证与对Action的权限控制
.NET WebAPI 用ActionFilterAttribute实现token令牌验证与对Action的权限控制 项目背景是一个社区类的APP(求轻吐...),博主主要负责后台业务及接口.以前没玩 ...
- MySQL聚合函数、控制流程函数
[正文] 一.navicat的引入:(第三方可视化的客户端,方便MySQL数据库的管理和维护) NavicatTM是一套快速.可靠并价格相宜的数据库管理工具,专为简化数据库的管理及降低系统管理成本而设 ...
- JavaScript---js语法,数据类型及方法, 数组及方法,JSON对象及方法,日期Date及方法,正则及方法,数据类型转换,运算符, 控制流程(三元运算),函数(匿名函数,自调用函数)
day46 一丶javascript介绍 JavaScript的基础分为三个 1.ECMAScript:JavaScript的语法标准.包括变量,表达式,运算符,函数,if语句,for语句 ...
- Azure Terraform(九)利用 Azure DevOps Pipeline 的审批来控制流程发布
一,引言 Azure Pipeline 管道是一个自动化过程:但是往往我们由于某种原因,需要在多个阶段之前获得批准之后再继续下一步流程,所以我们可以向Azure Pipeline 管道添加审批!批准流 ...
- asp.net 一个简单的登录控制
如果说一个网站需要用户登录后才能浏览,那么用户登录控制就不可避免.但是对于几百个以上的页面,不可能每个页面都做一次登录验证.因此,这需要在母版页中进行登录控制,这样就可以使得每一个使用这个母版页的子页 ...
- JavaScript(三)---- 控制流程语句
常用的控制流程语句有判断语句.分支语句.循环语句.基本用法都和java中的一致,switch有几点特殊. 1.判断语句 格式: if(判断条件){ 符合条件执行的代 ...
- 【JAVA零基础入门系列】Day8 Java的控制流程
什么是控制流程?简单来说就是控制程序运行逻辑的,因为程序一般而言不会直接一步运行到底,而是需要加上一些判断,一些循环等等.举个栗子,就好比你准备出门买个苹果,把这个过程当成程序的话,可能需要先判断一下 ...
随机推荐
- PLSQL过程创建和调用
存储过程 创建过程范例 create or replace procedure pro_kingsql_p1( p_one in varchar2,--可以传入参数 p_two out varchar ...
- 基于bind搭建DNS主从
使用bind的主从复制功能可以实现的功能:提供冗余,避免单点故障:均衡负载查询需求,从而提高系统可用性. 一.安装 #bind-chroot 负责DNS安全作用,将bind进程严格限制在特定的目录中 ...
- 2018/04/01 每日一个Linux命令 之 sleep
今天看到一个很有意思的指令. sleep [睡觉/休眠] 的意思. 可以用来将目前动作延迟一段时间.之后触发 -- sleep number[smhd] 重要参数 number : 时间长度,后面可接 ...
- LightOj 1030 - Discovering Gold(dp+数学期望)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1030 题意:在一个1*n 的格子里,每个格子都有相应的金币数,走到相应格子的话,就会得 ...
- Python装饰器与面向切面编程(转)
add by zhj: 装饰器的作用是将代码中可以独立的功能独立出来,实现代码复用,下面那个用于统计函数运行时间的装饰器就是很好的例子,我们不用修改原有的函数和调用原有函数的地方,这遵循了开闭原则.装 ...
- CentOS配置JDK环境
1 .下载JDK,jdk1.7.0_80.gz 2. mkdir -p /usr/lib/java 3.sudo chmod -R 777 /usr/lib/java 4.tar -zxvf jdk1 ...
- 【Jmeter】如何通过文件导入方式对用户名和密码进行参数化设置
JMeter 参数化 注意:param和data body只能用一个.所有任何一个里面有内容,切换都会报错,这不是问题,jmeter是这么设计的 方法一:通过添加CSV Data Set Config ...
- 如何批量删除SQL注释?
如何批量删除SQL注释.. 这个,可能是用来干坏事的吧.不过有时候要做一些重构,也还是有用.嘿嘿 使用工具,notepad++,注意要选择正则表达式按钮才行. [1]删除 /* */ /\*{1, ...
- 学JS必看-JavaScript数据结构深度剖析
回归简单 要理解JavaScript,你得首先放下对象和类的概念,回到数据和代码的本原.前面说过,编程世界只有数据和代码两种基本元素,而这两种元素又有着纠缠不清的关系.JavaScript就是把数据和 ...
- Amazon SES SPF和DKIM设置教程
SPF和DKIM设置是争对域名邮箱而言的(公共邮件也不会给你修改DNS的权限),主要作用就是防止邮箱伪造提升邮件信用度 首先到亚马逊添加域名并验证 添加后,给出了域名验证的方法,就是在dns记录里添加 ...