背景:

先上个图,看一下效果:

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)|禁止重复登陆|登录强制下线的更多相关文章

  1. SSH公钥登录且禁止密码登录及更改默认端口

    1.ssh生成公私钥 ssh-keygen -t rsa -C "zhangsan@qq.com" 生成密钥的位置如下,id_rsa是私钥.id_rsa.pub是公钥: ➜ .ss ...

  2. 服务器使用ssh秘钥登录并禁止密码登录

    问题: 最近在登录服务器的时候,每次都会有提示999+ falied login等字眼,意思就是自己的服务器密码正在被人暴力破解.想象以下,别人有了你的服务器的root登录密码,那么就可以对你的服务器 ...

  3. asp.net mvc 权限过滤和单点登录(禁止重复登录)

    1.权限控制使用controller和 action来实现,权限方式有很多种,最近开发项目使用控制控制器方式实现代码如下 /// <summary> /// 用户权限控制 /// < ...

  4. 单点登录 SSO, 自动登录 , java 加密,ssl原理, Tomcat配置SSL

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 单点登录的英文简称为SSO(single sign on),单点登录功能使得用户只要登录 ...

  5. 配置sshd_config中的PermitRootLogin设置root登录或者禁止root登录

    在etc的sshd_config文件中,默认有PermitRootLogin no的配置,这个的意思是禁止root用户登录,如果想要允许root登录,需要su root用户到sshd_config下进 ...

  6. SSH使用密钥登录并禁止密码登录

    #1 新建用于登录的用户useradd -p `echo "KYmO4ClPt1" | openssl passwd -1 -salt $(< /dev/urandom tr ...

  7. SSH使用密钥登录并禁止口令登录实践

    生成PublicKey Linux:ssh-keygen -t rsa[私钥 (id_rsa) 与公钥 (id_rsa.pub)]Windows:SecurCRT/Xshell/PuTTY[SSH-2 ...

  8. 允许FTP用户登录并禁止Shell登录的方法

    最近安装了vsftpd做FTP服务,发现系统用户的登录shell设置为/sbin/nologin,就无法使用FTP服务.网上资料说,vsftpd会为每个FTP登录用户去在/etc/shells中检查对 ...

  9. SSH 使用密钥登录并禁止口令登录

    小结:修改下sshd配置文件,把公钥传上去就好了 先生成公钥和私钥,默认在/root/.ssh/目录,可以先看一下有没有这个目录. 生成公钥后,以后其它服务器也都可以复用这个公钥 最好生成时输入密码! ...

  10. Asp.Net Core基于Cookie实现同域单点登录(SSO)

    在同一个域名下有很多子系统 如:a.giant.com  b.giant.com   c.giant.com等 但是这些系统都是giant.com这个子域. 这样的情况就可以在不引用其它框架的情况下, ...

随机推荐

  1. ASP.NET MVC 性能优化和调试

    学习 .NET Core 应用程序的调试技术可以分为以下步骤: 理解基础概念:首先,你需要理解什么是调试以及为什么我们需要调试.理解断点.单步执行.变量监视等基本调试概念. 学习 Visual Stu ...

  2. 力扣434(java)-字符串中的单词个数(简单)

    题目: 统计字符串中的单词个数,这里的单词指的是连续的不是空格的字符. 请注意,你可以假定字符串里不包括任何不可打印的字符. 示例: 输入: "Hello, my name is John& ...

  3. CF1857G Counting Graphs 题解

    题目描述 给定一棵最小生成树,求有多少张图的最小生成树是给定的树,并且这张图的所有边边权不超过 \(S\). 思路 考虑在最小生成树中加边. 我们回顾一下 Kruskal 的过程: 找到没被用过的,最 ...

  4. 宏杉科技加入阿里云PolarDB开源数据库社区

    简介: 宏杉科技签署阿里巴巴开源CLA(Contribution License Agreement, 贡献许可协议), 正式与阿里云PolarDB 开源数据库社区牵手. 宏杉科技签署阿里巴巴开源CL ...

  5. 平行云CEO 李岩:CloudXR ,开启通往元宇宙的通道

    ​简介:一端是算力无穷的云,这也是 CloudXR 的精髓所在. ​ 图:2022阿里云视觉计算私享会现场 5月11日,在"2022阿里云视觉计算私享会"上,平行云CEO李岩为大家 ...

  6. WPF 制作一个占用文件的测试工具

    我在开发软件进行测试时,需要测试拖入的文件被占用时软件的行为,于是就做了一个文件占用工具,此工具可以将某个文件进行占用,以及获取某个文件被哪个进程占用 先给大家看一下效果: 以上是拖入文件到灰色部分, ...

  7. SQL SERVER数据库存储过程加密

    CREATE PROCEDURE [dbo].[kytj_Base_Worker] WITH ENCRYPTION AS SELECT u.worker_number, u.worker_name, ...

  8. EPAI手绘建模APP资源管理和模型编辑器2

    g) 矩形   图 26模型编辑器-矩形 i. 修改矩形的中心位置. ii. 修改矩形的长度和宽度. h) 正多边形 图 27模型编辑器-内接正多边形 图 28模型编辑器-外切正多边形 i. 修改正多 ...

  9. 再聊解除HiddenApi限制

    炒冷饭,再聊聊大家都知晓的隐藏接口的限制解除. 说明 由于我们容器产品的特性,需要将应用完整的运行起来,所以必须涉及一些隐藏接口的反射调用,而突破反射限制则成为我们实现的基础.现将我们的解决方案分享给 ...

  10. C++ Grammar Focus

    一.结构体 1.基础模板 struct Node { <变量类型1> 变量名1; <变量类型2> 变量名2; ... } <定义变量名1>,<定义变量名2&g ...