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

相关文章

kali linux 无法登录root的问题及解决方法

《kalilinux无法登录root的问题及解决方法》:本文主要介绍kalilinux无法登录root的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录kali linux 无法登录root1、问题描述1.1、本地登录root1.2、ssh远程登录root2、

springboot security验证码的登录实例

《springbootsecurity验证码的登录实例》:本文主要介绍springbootsecurity验证码的登录实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录前言代码示例引入依赖定义验证码生成器定义获取验证码及认证接口测试获取验证码登录总结前言在spring

最新Spring Security实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)

《最新SpringSecurity实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)》本章节介绍了如何通过SpringSecurity实现从配置自定义登录页面、表单登录处理逻辑的配置,并简单模拟... 目录前言改造准备开始登录页改造自定义用户名密码登陆成功失败跳转问题自定义登出前后端分离适配方案结语前言

Oracle登录时忘记用户名或密码该如何解决

《Oracle登录时忘记用户名或密码该如何解决》:本文主要介绍如何在Oracle12c中忘记用户名和密码时找回或重置用户账户信息,文中通过代码介绍的非常详细,对同样遇到这个问题的同学具有一定的参... 目录一、忘记账户:二、忘记密码:三、详细情况情况 1:1.1. 登录到数据库1.2. 查看当前用户信息1.

MobaXterm远程登录工具功能与应用小结

《MobaXterm远程登录工具功能与应用小结》MobaXterm是一款功能强大的远程终端软件,主要支持SSH登录,拥有多种远程协议,实现跨平台访问,它包括多会话管理、本地命令行执行、图形化界面集成和... 目录1. 远程终端软件概述1.1 远程终端软件的定义与用途1.2 远程终端软件的关键特性2. 支持的

Oracle数据库如何切换登录用户(system和sys)

《Oracle数据库如何切换登录用户(system和sys)》文章介绍了如何使用SQL*Plus工具登录Oracle数据库的system用户,包括打开登录入口、输入用户名和口令、以及切换到sys用户的... 目录打开登录入口登录system用户总结打开登录入口win+R打开运行对话框,输php入:sqlp

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 :