CAS单点登录-单用户登录(十九)

2024-05-15 17:48

本文主要是介绍CAS单点登录-单用户登录(十九),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

CAS单点登录-单用户登录(十九)

简介

所谓“单用户单账户登录”是指:在同一系统中,一个用户名不能在两个地方同时登录。

如:
当某账号在 A 处登录后,在未退出的情况下,如果再到 B 处登录,那么,系统会挤下 A 处登录的账号

程序逻辑

我们一路学习cas过来应该知道如下知识

  1. 维持一个用户状态是用tgt
  2. 用户登录成功后tgt会创建
  3. 业务系统验证成功是采用st的校验
  4. 用户注销相当于删除tgt
  5. 删除tgt采用CentralAuthenticationService.destroyTicketGrantingTicket

有以上的知识我们即可对其他用户的提出,程序应该满足以下逻辑:

  1. 监听tgt创建事件
  2. 获取用户id,以及tgt
  3. 根据用户id,认证方式clientName寻找所有的tgt
  4. 过滤非当前用户的tgt的所有tgt
  5. 删除过滤后的tgt(正确的逻辑过滤后一般情况剩下一个,因为已经单用户登录了)

第三点详解:
为什么要采用clientName进行过滤呢,因为认证平台可能通过restful认证,qq、github、微信的OAuth2认证等等,所以认证方式不同,最后的用户id以及clientName会不同,所以要根据用户认证方式以及id,找到所有该用户的认证方式进行删除tgt,否则会出现,oauth2登录的用户用账号登录无法强制注销

实战

TGT创建监听

这个监听是为了用户登录成功后对其他用户进行剔除

TGTCreateEventListener.java

/** 版权所有.(c)2008-2017. 卡尔科技工作室*/package com.carl.sso.support.single.listener;import com.carl.sso.support.single.service.IUserIdObtainService;
import com.carl.sso.support.single.service.TriggerLogoutService;
import org.apereo.cas.support.events.ticket.CasTicketGrantingTicketCreatedEvent;
import org.apereo.cas.ticket.TicketGrantingTicket;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;import javax.validation.constraints.NotNull;
import java.util.List;/*** 识别事件然后删除** @author Carl* @version 创建时间:2017/11/29*/
public class TGTCreateEventListener {private TriggerLogoutService logoutService;private IUserIdObtainService service;public TGTCreateEventListener(@NotNull TriggerLogoutService logoutService, @NotNull IUserIdObtainService service) {this.logoutService = logoutService;this.service = service;}@EventListener@Asyncpublic void onTgtCreateEvent(CasTicketGrantingTicketCreatedEvent event) {TicketGrantingTicket ticketGrantingTicket = event.getTicketGrantingTicket();String id = ticketGrantingTicket.getAuthentication().getPrincipal().getId();String tgt = ticketGrantingTicket.getId();String clientName = (String) ticketGrantingTicket.getAuthentication().getAttributes().get("clientName");//获取可以认证的idList<String> authIds = service.obtain(clientName, id);if (authIds != null) {//循环触发登出authIds.forEach(authId -> logoutService.triggerLogout(authId, tgt));}}
}

剔除过滤用户

根据用户id,tgt,筛选出用户,并剔除

TriggerLogoutService.java

/** 版权所有.(c)2008-2017. 卡尔科技工作室*/package com.carl.sso.support.single.service;import org.apereo.cas.CentralAuthenticationService;
import org.apereo.cas.authentication.Authentication;
import org.apereo.cas.ticket.Ticket;
import org.apereo.cas.ticket.TicketGrantingTicket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.Collection;/*** 登出触发器** @author Carl* @date 2017/11/29*/
public class TriggerLogoutService {private static final Logger LOGGER = LoggerFactory.getLogger(TriggerLogoutService.class);private CentralAuthenticationService service;public TriggerLogoutService(CentralAuthenticationService service) {this.service = service;}/*** 触发其他用户退出** @param id  用户id* @param tgt 当前登录的tgt*/public void triggerLogout(String id, String tgt) {//找出用户id,并且不为当前tgt的,这里应当考虑数据性能,直接筛选用户再筛选tgtCollection<Ticket> tickets = this.service.getTickets(ticket -> {if(ticket instanceof TicketGrantingTicket) {TicketGrantingTicket t = ((TicketGrantingTicket)ticket).getRoot();Authentication authentication = t.getAuthentication();return t != null && authentication != null&& authentication.getPrincipal() != null && id.equals(authentication.getPrincipal().getId())&& !tgt.equals(t.getId());} else {return false;}});if (tickets != null && tickets.size() > 0) {LOGGER.info(String.format("[%s]强制强制注销%s", id, tickets.size()));}//发出注销for (Ticket ticket : tickets) {service.destroyTicketGrantingTicket(ticket.getId());}}
}

获取用户id

UserIdObtainServiceImpl.java

/** 版权所有.(c)2008-2017. 卡尔科技工作室*/package com.carl.sso.support.single.service;import java.util.ArrayList;
import java.util.List;/*** @author Carl* @version 创建时间:2017/11/29*/
public class UserIdObtainServiceImpl implements IUserIdObtainService {public UserIdObtainServiceImpl() {}@Overridepublic List<String> obtain(String clientName, String id) {//由于这里目前只做测试所以只返回当前的id,在正常的情况逻辑应该如下//根据校验client以及登录的id找到其他同一个用户的所有校验id返回,如通过邮箱登录的id,通过github登录的id等等List<String> ids = new ArrayList<>();ids.add(id);return ids;}
}

spring配置注册

SingleLogoutTriggerConfiguration.java

/** 版权所有.(c)2008-2017. 卡尔科技工作室*/package com.carl.sso.support.single.config;import com.carl.sso.support.single.listener.TGTCreateEventListener;
import com.carl.sso.support.single.service.TriggerLogoutService;
import com.carl.sso.support.single.service.UserIdObtainServiceImpl;
import org.apereo.cas.CentralAuthenticationService;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 登出配置** @author Carl* @date 2017/11/29*/
@Configuration("singleLogoutTriggerConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
public class SingleLogoutTriggerConfiguration {@Autowiredprivate CentralAuthenticationService centralAuthenticationService;/*** 触发登出服务** @return 触发登出服务*/@Beanprotected TriggerLogoutService triggerLogoutService() {return new TriggerLogoutService(centralAuthenticationService);}@Bean//注册事件监听tgt的创建protected TGTCreateEventListener tgtCreateEventListener() {TGTCreateEventListener listener = new TGTCreateEventListener(triggerLogoutService(), new UserIdObtainServiceImpl());return listener;}
}

测试

代码提交可以参考github提交

测试流程:

在chrome浏览器登陆,然后在IE浏览器登陆同样的账号,chrome浏览器的用户已登出

下载代码尝试:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aOLNA5A3-1611805583688)(https://img.shields.io/badge/downloads-v1.7.0=RC1-brightgreen.svg)] 其他版本可以到GitHub或者码云查看

发现一些意外的事情可以考虑翻翻前面的博客进行学习哦

作者联系方式

如果技术的交流或者疑问可以联系或者提出issue。

邮箱:huang.wenbin@foxmail.com

QQ: 756884434 (请注明:SSO-CSDN)

这篇关于CAS单点登录-单用户登录(十九)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/992506

相关文章

python实现自动登录12306自动抢票功能

《python实现自动登录12306自动抢票功能》随着互联网技术的发展,越来越多的人选择通过网络平台购票,特别是在中国,12306作为官方火车票预订平台,承担了巨大的访问量,对于热门线路或者节假日出行... 目录一、遇到的问题?二、改进三、进阶–展望总结一、遇到的问题?1.url-正确的表头:就是首先ur

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

【重学 MySQL】十九、位运算符的使用

【重学 MySQL】十九、位运算符的使用 示例检查权限添加权限移除权限 在 MySQL 中,位运算符允许你直接在整数类型的列或表达式上进行位级操作。这些操作对于处理那些需要在二进制表示上进行直接修改或比较的场景特别有用,比如权限管理、状态标记等。 &(位与) 对两个数的二进制表示进行位与操作。只有两个相应的二进制位都为 1 时,结果的该位才为 1,否则为 0。 |(位

Shell脚本实现自动登录服务器

1.登录脚本 login_server.sh #!/bin/bash# ReferenceLink:https://yq.aliyun.com/articles/516347#show all host infos of serverList.txtif [[ -f ./serverList.txt ]]thenhostNum=`cat ./serverList.txt | wc -l`e

SpringBoot登录退出|苍穹外卖登录退出分析

文章目录 概要整体流程注意事项一、拦截路径二、token三、注册防止用户重复提交 苍穹外卖登录退出分析注意解决JWT退出后依然有效的问题 概要 结合Spring Boot和Vue3实现安全的用户登录和退出功能,并使用拦截器、JWT和Redis缓存来提高系统的安全性和性能。 整体流程 注意事项 一、拦截路径 像登录页面的路径就不要拦截了,否则都不能登录了 例如:

Node.js和vue3实现GitHub OAuth第三方登录

Node.js和vue3实现GitHub OAuth第三方登录 前言 第三方登入太常见了,微信,微博,QQ…总有一个你用过。 在开发中,我们希望用户可以通过GitHub账号登录我们的网站,这样用户就不需要注册账号,直接通过GitHub账号登录即可。 效果演示 注册配置 GitHub 应用 1.首先登录你的GitHub然后点击右上角的头像->点击进入Settings页面 2.在

三方登录 - 华为登录

1.1. 开发准备 当应用需要使用以下开放能力的一种或多种时,为正常调试运行应用,需要预先添加公钥指纹 Account Kit(华为帐号服务)Call Kit(通话服务)Game Service Kit(游戏服务)Health Service Kit(运动健康服务)IAP Kit(应用内支付服务)Live View Kit(实况窗服务,当需要使用Push Kit时必须执行此步骤)Map Kit

web登录校验

基础登录功能 LoginController @PostMapping("/login")Result login(@RequestBody Emp emp) {log.info("前端,发送了一个登录请求");Emp e = empService.login(emp);return e!=null?Result.success():Result.error("用户" +"名或密码错误");