惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threatpost
aimingoo的专栏
aimingoo的专栏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Tailwind CSS Blog
J
Java Code Geeks
博客园_首页
Google Online Security Blog
Google Online Security Blog
Hugging Face - Blog
Hugging Face - Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
I
Intezer
P
Palo Alto Networks Blog
V
Vulnerabilities – Threatpost
雷峰网
雷峰网
O
OpenAI News
SecWiki News
SecWiki News
小众软件
小众软件
酷 壳 – CoolShell
酷 壳 – CoolShell
美团技术团队
N
News | PayPal Newsroom
Project Zero
Project Zero
Forbes - Security
Forbes - Security
IT之家
IT之家
A
Arctic Wolf
WordPress大学
WordPress大学
Jina AI
Jina AI
T
Tor Project blog
博客园 - 三生石上(FineUI控件)
S
Secure Thoughts
Google DeepMind News
Google DeepMind News
Attack and Defense Labs
Attack and Defense Labs
博客园 - 聂微东
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Privacy International News Feed
Cloudbric
Cloudbric
G
GRAHAM CLULEY
博客园 - 叶小钗
H
Hacker News: Front Page
腾讯CDC
量子位
Help Net Security
Help Net Security
人人都是产品经理
人人都是产品经理
C
Cyber Attacks, Cyber Crime and Cyber Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
宝玉的分享
宝玉的分享
爱范儿
爱范儿
L
Lohrmann on Cybersecurity
Hacker News - Newest:
Hacker News - Newest: "LLM"
Recorded Future
Recorded Future
C
CERT Recently Published Vulnerability Notes

博客园 - lichdr

高德地图热力图的Flutter实现 App消息推送的简单实现 nginx访问日志过滤(多条件) CAS的service参数验证 单元格的计算 表格行列的删除 表格行列的移动 FastReport的一些另类用法 FastReport分组页码 RFID会议签到系统总结(二十二)――系统中的模式 RFID会议签到系统总结(二十一)――服务端的通讯 RFID会议签到系统总结(二十)――数据窗体状态控制 RFID会议签到系统总结(十九)――单数据窗体 RFID会议签到系统总结(十八)――菜单与工具栏的加载 RFID会议签到系统总结(十七)――菜单与工具栏的改造(下) RFID会议签到系统总结(十六)――菜单与工具栏按钮的改造(上) RFID会议签到系统总结(十五)――管控端的窗体组织 RFID会议签到系统总结(十四)――管控端业务模块的加载 RFID会议签到系统总结(十三)――模块概述(下)
自定义Token的CAS登录
lichdr · 2019-01-25 · via 博客园 - lichdr

工作中实际遇到的需求,我们有一个旧系统,用了CAS的单点登录,现在有一个外部系统,准备从它那里单点进来,这个外部系统提供了一个token参数来标记这是哪一个用户,我们用他们提供的方式解析出对应的用户,以这个用户从CAS登录进系统。

有关CAS登录的分析网上多如牛毛,这里不准备多作分析了,直接上解决过程。

这里实现是基于我们以前系统的,是CAS 3.5.2

  • 首先在登录流程文件login-webflow.xml里在on-start节点后面插入
<decision-state id="tokenCheck">
   <if test="requestParameters.token != null and requestParameters.token != ''" then="tokenValidate" else="ticketGrantingTicketExistsCheck" />
</decision-state>

在这里检查是否有token参数,有的话执行token验证,没有的话走正常流程,ticketGrantingTicketExistsCheck就是原有的正常流程。

  • 定义token验证节点
<action-state id="tokenValidate">
   <evaluate expression="tokenLoginAction.doExecute(flowRequestContext)" />
   <transition on="error" to="generateLoginTicket" />
   <transition on="success" to="sendTicketGrantingTicket" />
</action-state>

失败则走generateLoginTicket分支,会生成一个LT,并重定向到登录页面,这也是通常页面登录失败后的路径

成功则走sendTicketGrantingTicket分支,即页面正常登录成功时走的路径

  • 实现token验证流程节点

在cas-servlet.xml里添加添加tokenLoginAction Bean

<bean id="tokenLoginAction" class="org.jasig.cas.web.flow.TokenLoginAction"
    p:centralAuthenticationService-ref="centralAuthenticationService" />

实现TokenLoginAction

这里主要解析token,并生成TGT。主要代码如下:

HttpServletRequest request = WebUtils.getHttpServletRequest(context);
String token = request.getParameter("token");

 try {

  //解析Token,略。。。。。。

   CasCredentials credentials = new CasCredentials();
   credentials.setUsername(userName);
   credentials.setPassword("");
   credentials.setNoAuth(true);
  
   String tgt = centralAuthenticationService.createTicketGrantingTicket(credentials);
   WebUtils.putTicketGrantingTicketInRequestScope(context,tgt);
  
 } catch (Exception e) {
   e.printStackTrace();
  return "error";
 }
 
 return "success";

TokenLoginAction的主要逻辑代码

上面centralAuthenticationService是注入的属性,

CasCredentials则是继承自UsernamePasswordCredentials的一个自定义Credentials,在用户名、密码基础上添加了一个noAuth属性,用来标记是不是需要验证密码。这里由外系统提供的token保证安全性,把noAuth设为true。

而登录验证逻辑在createTicketGrantingTicket这个方法里,验证未通过会抛出异常。

真正验证的地方则是在authenticationManager里,里面有authenticationHandlers定义了验证方法

  • 修改登录验证逻辑

login-webflow.xml顶部把credentials的定义先改了

<var name="credentials" class="com.cas.util.CasCredentials" />

deployerConfigContext.xml找到自定义登录验证所在

<bean id="authenticationManager" class="">
   <property name="authenticationHandlers">
  <list>
                           <bean
    class="com.cas.util.QueryUserAuthenticationHandler">
......
                           </bean>
                       </list>
   </property>
</bean>

在这个QueryUserAuthenticationHandler class里,验证密码之前加入

  if (CasCredentials.class.isInstance(credentials)) {
   if (((CasCredentials)credentials).isNoAuth())
    return true;
  }

这样就完成了传入第三方token的CAS登录。

似乎是完成了,但其实还有一些东西,

比如第三方进来的时候是不用他们传Service这个参数的,而这个参数是在CAS登录初始化时处理掉的,后面没有地方自己往request里加这个参数让CAS来处理它,自己写requestscope里写Service对象又很麻烦,看了下代码,得注入很多东西才行。这样就在进入CAS流程前,自己往请求里塞一个Service参数,然后重定向到CAS登录的url。

再比如,这次是别人提供Token用他们的方法解;以后有需求是我们提供一个Token出去,接收进来后用我们的方法自己解。所以其实TokenLoginAction那里解析Token其实是解本方提供出去的Token。解别人的Token呢前置到塞Service参数那个地方,那里解析出来用户名后,再用自己的方法生成一个Token发给CAS。这样就把第三方的Token解析分离出去了,CAS登录的地方不会跟别人的实现绑在一起。