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的控制流程
什么是控制流程?简单来说就是控制程序运行逻辑的,因为程序一般而言不会直接一步运行到底,而是需要加上一些判断,一些循环等等.举个栗子,就好比你准备出门买个苹果,把这个过程当成程序的话,可能需要先判断一下 ...
随机推荐
- PL/SQL自定义函数
从SQL表达式中调用函数的限制 为了从SQL表达式中调用函数,一个用户定义函数必须: 是存储函数 只接受IN函数 只接收有受的SQL数据类型,而不接受PL/SQL数据类型 返回数据类型为有效的SQL数 ...
- Zhu and 772002---hdu5833(高斯消元解求异或方程组)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5833 题意:给n个数,选择一些数字乘积为平方数的选择方案数. 分析:每一个数字分解质因数.比如4, 6 ...
- DLL远程注入及卸载实现
实现win7 64位系统下dll的远程注入及卸载,尚未再其他系统测试 源码地址:https://github.com/ndhisrfzs/InjectDll
- Java bytesToHexString 解析
一.代码 /** * Convert byte[] to hex string * * @param src byte[] data * @return hex string */ public st ...
- LINUX的前后台程序查看切换
1.在Linux终端运行命令的时候,在命令末尾加上 & 符号,就可以让程序在后台运行 root@Ubuntu$ ./tcpserv01 & 2.如果程序正在前台运行,可以使用 Ctrl ...
- awesome go library 库,推荐使用的golang库
https://github.com/avelino/awesome-go https://github.com/spf13/cobra # A Comm ...
- Centos 7(Linux)环境下安装PHP(编译添加)相应动态扩展模块so(以openssl.so为例)
https://blog.csdn.net/shinesun001/article/details/54312402 在centos 7环境下搭建好Lnmp环境之后,发现安装的php有好多扩展都没有安 ...
- mybatis中获取参数
1.${parameter}方式: parameter是数字时用:模糊查询%${parameter}%时用. 例:select * from account where userId = ${para ...
- Razor中的@:和语法
用Razor实现流畅编程 Razor尽量减少编写一个视图模板需要敲入的字符数,实现快速流畅的编程工作流.与大部分模板的语法不同,你不必在HTML中为了明确地标记出服务模块 的开始和结束而中断编程.Ra ...
- liferay6.1.2的API
http://docs.liferay.com/portal/6.1/javadocs/overview-summary.html