Asp.Net 单点登录(SSO)|禁止重复登陆|登录强制下线
背景:
先上个图,看一下效果:

SSO英文全称Single Sign On(单点登录)。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的登录映射到其他应用中用于同一个用户的登录的机制。
它是目前比较流行的企业业务整合的解决方案之一。(本段内容来自百度百科) 话不多说,开撸!
逻辑分析:
Client1:用户A在电脑1上登录管理员账号
Service:验证用户A登陆成功生成Admin账号的Token令牌,分别存储电脑1的cookie中和服务器的全局变量中(可以是session,缓存,全局变量,数据库)
Client2:用户B在电脑2上登录管理员账号
Service:验证用户B登陆成功重新生成Admin账号的Token令牌,分别存储电脑2的cookie中和服务器的全局变量中(可以是session,缓存,全局变量,数据库)
Client1:触发验证:
1,判断服务器全局变量是否过期,提示:身份信息过期,请重新登录。
2,判断客户端的cookie是否过期,提示:长时间未登录,已下线。
3,判断电脑1上的cookie与服务器全局变量相比是否一致。提示:此用户已在别处登陆!你被强制下线!
代码实现
Service:
1,创建一个服务器校验登录类,代码如下
using Coldairarrow.Business;
using Coldairarrow.Util;
using System;
using System.Text;
using System.Web.Mvc; namespace Coldairarrow.Web
{
/// <summary>
/// 校验登录
/// </summary>
public class CheckLoginAttribute : FilterAttribute, IActionFilter
{
public IOperator _operator { get; set; }
public ILogger _logger { get; set; } /// <summary>
/// Action执行之前执行
/// </summary>
/// <param name="filterContext">过滤器上下文</param>
public void OnActionExecuting(ActionExecutingContext filterContext)
{
var request = filterContext.RequestContext.HttpContext.Request;
try
{
//若为本地测试,则不需要登录
if (GlobalSwitch.RunModel == RunModel.LocalTest)
{
return;
} //判断是否需要登录
bool needLogin = !filterContext.ContainsAttribute<IgnoreLoginAttribute>(); //获取session里面的用户id
var uid = SessionHelper.Session["UserId"]?.ToString(); if (needLogin)
{
if (string.IsNullOrEmpty(uid))
{ //转到登录
RedirectToLogin(); }
else
{
var Cguid = filterContext.HttpContext.Request.Cookies["CToken"].Value?.ToString();
var Sguid = CacheHelper.Cache.GetCache(uid + "_SToken")?.ToString(); //判断是否过期
if (string.IsNullOrEmpty(Cguid) || string.IsNullOrEmpty(Sguid))
{
// 过期 转到登录
ReturnLogin("身份信息以失效,请重新登陆!");
SessionHelper.Session["UserId"] = "";
}
else
{
//判断用户是否重复登陆
if (Sguid != Cguid)
{
// 过期 转到登录
ReturnLogin("此用户已在别处登陆!你被强制下线!");
SessionHelper.Session["UserId"] = "";
//message = "已登陆";
}
} } } //if (needLogin && !_operator.Logged())
//{ //转到登录
// RedirectToLogin();
//}
//else
//{ // string Id = _operator.UserId;
// _operator.Login(Id);
// return;
//}
}
catch (Exception ex)
{
_logger.Error(ex);
RedirectToLogin();
} void RedirectToLogin()
{
if (request.IsAjaxRequest())
{
filterContext.Result = new ContentResult
{
Content = new AjaxResult { Success = false, ErrorCode = 1, Msg = "未登录" }.ToJson(),
ContentEncoding = Encoding.UTF8,
ContentType = "application/json"
};
}
else
{
UrlHelper urlHelper = new UrlHelper(filterContext.RequestContext);
string loginUrl = urlHelper.Content("~/Home/Login");
string script = $@"
<html>
<script>
top.location.href = '{loginUrl}';
</script>
</html>
";
filterContext.Result = new ContentResult { Content = script, ContentType = "text/html", ContentEncoding = Encoding.UTF8 };
}
} void ReturnLogin(string msg)
{
UrlHelper urlHelper = new UrlHelper(filterContext.RequestContext);
string loginUrl = urlHelper.Content("~/Home/Login");
string script = $@"
<html>
<script>
alert('{msg}');
top.location.href = '{loginUrl}';
</script>
</html>
";
filterContext.Result = new ContentResult { Content = script, ContentType = "text/html", ContentEncoding = Encoding.UTF8 };
}
} /// <summary>
/// Action执行完毕之后执行
/// </summary>
/// <param name="filterContext"></param>
public void OnActionExecuted(ActionExecutedContext filterContext)
{ }
}
}
2,创建一个mvc基控制器继承Controller并且引用特性【CheckLogin】

3,业务控制器继承BaseMvcController,并编写登录代码。登陆成功后调用login方法,代码如下:

/// <summary>
/// 登录
/// </summary>
/// <param name="userId">用户逻辑主键Id</param>
public void Login(string userId)
{
//保存登陆成功的令牌
string Guid_str = "";
//分配一个唯一标识符
Guid_str = GuidHelper.GuidTo16String();
HttpContext.Current.Response.Cookies["CToken"].Value = Guid_str;
//给系统变量存储一个值,Uid代表哪个用户,GUID则是唯一标识符
CacheHelper.Cache.SetCache(userId + "_SToken", Guid_str, new TimeSpan(0, 0, 30, 0, 0), ExpireType.Absolute);
SessionHelper.Session["UserId"] = userId;
}
4,这个时候基本就结束了,还需要增加一个忽略验证的类,这个特性加在登录页面。意思是登录页面不需要触发验证;


5,服务器验证的核心代码有点不优雅,不过实现逻辑了。有问题可以评论区沟通一下。本人用的是将token分别存储在服务器缓存+客户端cookie完成 ,大家服务器上可以用session,缓存,全局变量,数据库等任意方式实现;
总结:
当用户没有重复登陆时,系统分配一个guid给用户,并记录用户id和对应的guid,这个用户在线时系统变量存储的用户id以及对应的guid值是不会变的,这时候有另外一个人用相同的账号登陆时,会改变系统变量中用户id对应的guid。
这时候服务器就判断出系统变量存储的guid与用户cookie存储的guid不同时,就会强制用户下线。
这个可以升级为指定N台设备登录,并且可以增加socket的方式通知其他电脑下线。由于业务不需要,就没有增加即时通讯。感谢观看。
Asp.Net 单点登录(SSO)|禁止重复登陆|登录强制下线的更多相关文章
- SSH公钥登录且禁止密码登录及更改默认端口
1.ssh生成公私钥 ssh-keygen -t rsa -C "zhangsan@qq.com" 生成密钥的位置如下,id_rsa是私钥.id_rsa.pub是公钥: ➜ .ss ...
- 服务器使用ssh秘钥登录并禁止密码登录
问题: 最近在登录服务器的时候,每次都会有提示999+ falied login等字眼,意思就是自己的服务器密码正在被人暴力破解.想象以下,别人有了你的服务器的root登录密码,那么就可以对你的服务器 ...
- asp.net mvc 权限过滤和单点登录(禁止重复登录)
1.权限控制使用controller和 action来实现,权限方式有很多种,最近开发项目使用控制控制器方式实现代码如下 /// <summary> /// 用户权限控制 /// < ...
- 单点登录 SSO, 自动登录 , java 加密,ssl原理, Tomcat配置SSL
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 单点登录的英文简称为SSO(single sign on),单点登录功能使得用户只要登录 ...
- 配置sshd_config中的PermitRootLogin设置root登录或者禁止root登录
在etc的sshd_config文件中,默认有PermitRootLogin no的配置,这个的意思是禁止root用户登录,如果想要允许root登录,需要su root用户到sshd_config下进 ...
- SSH使用密钥登录并禁止密码登录
#1 新建用于登录的用户useradd -p `echo "KYmO4ClPt1" | openssl passwd -1 -salt $(< /dev/urandom tr ...
- SSH使用密钥登录并禁止口令登录实践
生成PublicKey Linux:ssh-keygen -t rsa[私钥 (id_rsa) 与公钥 (id_rsa.pub)]Windows:SecurCRT/Xshell/PuTTY[SSH-2 ...
- 允许FTP用户登录并禁止Shell登录的方法
最近安装了vsftpd做FTP服务,发现系统用户的登录shell设置为/sbin/nologin,就无法使用FTP服务.网上资料说,vsftpd会为每个FTP登录用户去在/etc/shells中检查对 ...
- SSH 使用密钥登录并禁止口令登录
小结:修改下sshd配置文件,把公钥传上去就好了 先生成公钥和私钥,默认在/root/.ssh/目录,可以先看一下有没有这个目录. 生成公钥后,以后其它服务器也都可以复用这个公钥 最好生成时输入密码! ...
- Asp.Net Core基于Cookie实现同域单点登录(SSO)
在同一个域名下有很多子系统 如:a.giant.com b.giant.com c.giant.com等 但是这些系统都是giant.com这个子域. 这样的情况就可以在不引用其它框架的情况下, ...
随机推荐
- 图片验证码识别,标签中onehot编码对应多个1怎么做?
一张验证码图片直接做整体识别 也就是图片的最后输出节点有4*26=104个,经过一个softmax,使用交叉熵损失,与真实值4*26=104个标签做计算,然后反向传播 104个onehot编码真实值当 ...
- 第八課-Channel Study For Caller Custom JAR Lib
1.下载 apache-maven 推荐3.6.3版本:https://maven.apache.org/download.cgi 设置系统环境变量:PATH 装好后在命令行验证:mvn -v Mav ...
- 力扣73(java)-矩阵置零(中等)
题目: 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 .请使用 原地 算法. 提示: m == matrix.length n == matrix[0].l ...
- 融合数据库生态:利用 EventBridge 构建 CDC 应用
简介: 近期,EventBridge 事件流已经支持了基于阿里云 DTS服务的 CDC 能力.本文将从 CDC.CDC 在 EventBridge 上的应用以及若干最佳实践场景等方面,为大家介绍如何利 ...
- Spring Boot Serverless 实战系列“架构篇” 首发 | 光速入门函数计算
简介:如何以 Serverless 的方式运行 Spring Boot 应用? 作者 | 西流(阿里云函数计算专家) Spring Boot 是基于 Java Spring 框架的套件,它预装了 ...
- dotnet 写一个支持层层继承属性的对象
我最近在造一个比 Excel 差得多的表格控件,其中一个需求是属性的继承.大家都知道,表格里面有单元格,单元格里面允许放文本,文本可以放多段文本.本文的主角就是文本段落的样式属性,包括文本字体字号颜色 ...
- WPF 下拉框选项做鼠标 Hover 预览效果
本文来告诉大家如何在 WPF 中,在 下拉框 ComboBox 里面,鼠标移动到 ComboBoxItem 上时,自动触发对应的事件,用来预览此选项值.例如我在实现一个颜色下拉框,此时我可以通过点击下 ...
- Visual Studio 2019 自带混淆工具DotFuscator不需要去网络下载
http://t.zoukankan.com/daizhipeng-p-13492298.html 大家是否还在困扰发布的项目dll容易被人反编译呢,VS2019默认是没有安装DotFuscator的 ...
- github只下载某个文件或文件夹(使用GitZip插件)
安装GitZip插件 (此安装过程需要梯子(不懂"梯子",百度一下就明白)) 1. 打开插件管理页面 方法一:打开Chrome浏览器(Edge浏览器同理),在Chrom地址栏输入c ...
- Golang 之 casbin(权限管理)
目录 1. 权限管理 官网 编辑器测试 1.1.1. 特征 Casbin的作用 Casbin不执行的操作 1.1.2. 怎么运行的 1.1.3. 安装 1. 示例代码 xormadapter 2. 示 ...