CAS单点登录6 - 服务端自定义返回的用户信息

2023-05-16

原理

返回的用户信息是在deployerConfigContext.xml中的配置的

既然想自定义返回的用户信息,那么继承org.jasig.services.persondir.support.StubPersonAttributeDao就好了

1、创建com.jadyer.sso.authentication extends StubPersonAttributeDao并复写getPerson()方法

  使用@Component(value=”attributeRepository”)定义它的BeanID

2、注释deployerConfigContext.xml中的<bean id="attributeRepository"><util:map id="attrRepoBackingMap">配置

3、修改\WEB-INF\view\jsp\protocol\2.0\casServiceValidationSuccess.jsp(不要改3.0下面的)

具体改动,详见下方贴出的代码

另外:返回给客户端的相关信息是由org.jasig.services.persondir.IPersonAttributeDao接口定义的

StubPersonAttributeDao就是IPersonAttributeDao的实现之一

其它实现如SingleRowJdbcPersonAttributeDao、LdapPersonAttributeDao等

所以也可在deployerConfigContext.xml中配置的实现为SingleRowJdbcPersonAttributeDao

也就是<bean id="attributeRepository" class="org.jasig...persondir.support.jdbc.SingleRowJdbcPersonAttributeDao">

不过,个人觉得这样不是很灵活,所以就不贴示例代码了

代码

下面是自定义的控制返回的用户信息的UserStubPersonAttributeDao.java

 

package com.jadyer.sso.authentication;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.jasig.services.persondir.IPersonAttributes;
import org.jasig.services.persondir.support.AttributeNamedPersonImpl;
import org.jasig.services.persondir.support.StubPersonAttributeDao;
import org.springframework.stereotype.Component;
import com.jadyer.sso.model.User;

/**
 * 自定义的返回给客户端相关信息
 * Created by 玄玉<https://jadyer.github.io/> on 2015/07/18 17:52.
 */
@Component(value="attributeRepository")
public class UserStubPersonAttributeDao extends StubPersonAttributeDao {
    @Resource
    private UserDaoJdbc userDaoJdbc;
    @Override
    public IPersonAttributes getPerson(String uid) {
        Map<String, List<Object>> attributes = new HashMap<String, List<Object>>();
        try {
            User user = userDaoJdbc.getByUsername(uid);
            attributes.put("userId", Collections.singletonList((Object)user.getUsercode()));
            attributes.put("username", Collections.singletonList((Object)user.getUsername()));
            attributes.put("usernamePlain", Collections.singletonList((Object)URLEncoder.encode(user.getUsernamePlain(), "UTF-8")));
            attributes.put("blogURL", Collections.singletonList((Object)"https://jadyer.github.io/"));
            attributes.put("blogger", Collections.singletonList((Object)URLEncoder.encode("玄玉", "UTF-8")));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return new AttributeNamedPersonImpl(attributes);
    }
}

 

 

 

 

 

下面是用到的查询数据库的UserDaoJdbc.java

 

package com.jadyer.sso.authentication;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import com.jadyer.sso.model.User;

@Repository
public class UserDaoJdbc {
    private static final String SQL_USER_VERIFY = "SELECT COUNT(*) FROM permission_operator WHERE operator_login=? AND operator_pwd=SHA1(?)";
    private static final String SQL_USER_GET = "SELECT * FROM permission_operator WHERE operator_login=?";
    private JdbcTemplate jdbcTemplate;
    @Resource
    public void setDataSource(DataSource dataSource){
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }
    public boolean verifyAccount(String username, String password){
        try{
            //验证用户名和密码是否正确
            return 1==this.jdbcTemplate.queryForObject(SQL_USER_VERIFY, new Object[]{username, password}, Integer.class);
        }catch(EmptyResultDataAccessException e){
            return false;
        }
    }
    public User getByUsername(String username){
        try{
            //根据用户名获取用户信息
            return (User)this.jdbcTemplate.queryForObject(SQL_USER_GET, new Object[]{username}, new UserRowMapper());
        }catch(EmptyResultDataAccessException e){
            return new User();
        }
    }
}

class UserRowMapper implements RowMapper<User> {
    @Override
    public User mapRow(ResultSet rs, int index) throws SQLException {
        User user = new User();
        user.setUsercode(rs.getString("operator_code"));
        user.setUsername(rs.getString("operator_login"));
        user.setUsernamePlain(rs.getString("operator_name"));
        return user;
    }
}

 

下面是用到的User.java

 

package com.jadyer.sso.model;
public class User {
    private String usercode;
    private String username;
    private String usernamePlain;
    /*-- setter和getter略 --*/
}

 

下面是deployerConfigContext.xml的修改部分

 

<!-- 注释掉默认的attributeRepository实现,采用自定义的UserStubPersonAttributeDao -->
<!--
<bean id="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao"
       p:backingMap-ref="attrRepoBackingMap" />

<util:map id="attrRepoBackingMap">
   <entry key="uid" value="uid" />
   <entry key="eduPersonAffiliation" value="eduPersonAffiliation" />
   <entry key="groupMembership" value="groupMembership" />
</util:map>
-->

 

下面是\WEB-INF\view\jsp\protocol\2.0\casServiceValidationSuccess.jsp

 

<%--

    Licensed to Jasig under one or more contributor license
    agreements. See the NOTICE file distributed with this work
    for additional information regarding copyright ownership.
    Jasig licenses this file to you under the Apache License,
    Version 2.0 (the "License"); you may not use this file
    except in compliance with the License.  You may obtain a
    copy of the License at the following location:

      http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.

--%>
<%@ page session="false" contentType="application/xml; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
    <cas:authenticationSuccess>
        <cas:user>${fn:escapeXml(assertion.primaryAuthentication.principal.id)}</cas:user>
        <c:if test="${not empty pgtIou}">
                <cas:proxyGrantingTicket>${pgtIou}</cas:proxyGrantingTicket>
        </c:if>
        <c:if test="${fn:length(assertion.chainedAuthentications) > 1}">
          <cas:proxies>
            <c:forEach var="proxy" items="${assertion.chainedAuthentications}" varStatus="loopStatus" begin="0" end="${fn:length(assertion.chainedAuthentications)-2}" step="1">
                 <cas:proxy>${fn:escapeXml(proxy.principal.id)}</cas:proxy>
            </c:forEach>
          </cas:proxies>
        </c:if>
        <!--
        新增部分如下:CASServer验证成功后,该页面负责生成与客户端交互的XML信息
        默认的casServiceValidationSuccess.jsp中只包括用户名,并不提供其他的属性信息,因此需要对该页面进行扩展
        -->
        <c:if test="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes) > 0}">
            <cas:attributes>
                <c:forEach var="attr" items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}">
                    <cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}>
                </c:forEach>
            </cas:attributes>
        </c:if>
    </cas:authenticationSuccess>
</cas:serviceResponse>

 

最后是客户端获取服务端返回的自定义用户信息的index.jsp

 

<%@ page pageEncoding="UTF-8"%>
<%@ page import="java.util.Map"%>
<%@ page import="java.net.URLDecoder"%>
<%@ page import="org.jasig.cas.client.util.AssertionHolder"%>
<%@ page import="org.jasig.cas.client.authentication.AttributePrincipal"%>

<body style="background-color:#CBE0C9;">
    <span style="color:red; font-size:32px; font-weight:bold;">客户端登录成功</span>
</body>

<hr size="2">

<%
    AttributePrincipal principal = (AttributePrincipal)request.getUserPrincipal();
    Map<String, Object> attributes = principal.getAttributes();
    out.print("principal.getName()=" + principal.getName() + "<br/>");
    out.print("request.getRemoteUser()=" + request.getRemoteUser() + "<br/>");
    out.print("登录用户:" + attributes.get("userId") + "<br/>");
    out.print("登录时间:" + AssertionHolder.getAssertion().getAuthenticationDate() + "<br/>");
    out.print("-----------------------------------------------------------------------<br/>");
    for(Map.Entry<String, Object> entry : attributes.entrySet()){
        //服务端返回中文时需要encode,客户端接收显示中文时需要decode,否则会乱码
        out.print(entry.getKey() + "=" + URLDecoder.decode(entry.getValue().toString(), "UTF-8") + "<br/>");
    }
    out.print("-----------------------------------------------------------------------<br/>");
    Map<String, Object> attributes22 = AssertionHolder.getAssertion().getAttributes();
    for(Map.Entry<String, Object> entry : attributes22.entrySet()){
        out.print(entry.getKey() + "=" + entry.getValue() + "<br/>");
    }
    out.print("-----------------------------------------------------------------------<br/>");
    Map<String, Object> attributes33 = AssertionHolder.getAssertion().getPrincipal().getAttributes();
    for(Map.Entry<String, Object> entry : attributes33.entrySet()){
        out.print(entry.getKey() + "=" + entry.getValue() + "<br/>");
    }
%>

 

效果图

关于客户端如何配置(包括通过spring),详见本系列的下一篇博文

(今天头疼还发烧,明天再发客户端的配置方法)

将不定期更新资源,欢迎持续关注


想获得更多的学习知识请关注微信公众号:西北码农或扫下方二维码

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CAS单点登录6 - 服务端自定义返回的用户信息 的相关文章

随机推荐

  • Jetson tx2刷机过程中的坑

    暑假各种事忙得差不多后 xff0c 终于有时间拿出早就申请到的tx2 xff0c 开始刷机教程 xff0c 这两天几乎踩边了所有的坑 第一个坑 xff0c 虚拟机 一般在安装VMware虚拟机时 xff0c 建议的安装空间20GB xff0
  • python词云实现

    python的一个蛮酷炫的功能是可以轻松地实现词云 github上有关于这个项目的开源代码 xff1a https github com amueller word cloud 注意跑例程时要删除里面的wordcloud文件夹 词云的功能有
  • ubuntu18切换为gnome桌面托盘图标消失

    在软件菜单中选择 优化 拓展 gt Ubuntu appindicators xff0c 打开此项即可 效果
  • Expression #1 of ORDER BY clause is not in SELECT list, references column 'ekbX1.t0.name' which is n

    报错信息 xff1a Expression 1 of ORDER BY clause is not in SELECT list references column 39 ekbX1 t0 name 39 which is not in S
  • Archlinux + kde桌面环境 安装

    1 首先余留磁盘空间 2 xff1a 官网下载ArchLinux镜像 3 xff1a rufus刻录 4 xff1a 打开电脑从u盘启动 5 xff1a 首先联网 如果用wifi终端输入下面命令 xff1a wifi menu 如果是用网线
  • 判断图的连通子图个数

    题目要求 给定一个具有n个顶点 m条边的无向图G 假设项点的编号为1 n 基于深度优先搜索算法 xff0c 编写程序 求无向图G连通子图的个数 输入格式 第一行两个整数n m 分别表示图G的顶点数和边的数量 下面m行的每 行有两个整数a和b
  • Java常用包有哪些

    Java lang 语言包 Java语言的基础类 xff0c 包括Object类 Thread类 String Math System Runtime Class Exception Process等 xff0c 是Java的核心类库 最重
  • QT 建立透明背景图像QPixmap

    列将下面背景透明图片1转变成图片2 图1 图2 span class hljs preprocessor include 34 mainwindow h 34 span span class hljs preprocessor includ
  • Spring Boot——日志文件

    文章目录 1 日志的作用2 日志的用法3 自定义日志打印日志格式的说明 4 日志级别5 在配置文件中设置日志级别5 1设置全局的日志级别和局部文件夹的日志级别 6 日志持久化7 更简单的日志输出 lombok 1 日志的作用 日志的作用 x
  • VxWorks入门06:虚拟机中运行

    在下载的VxWorks安装包中 xff0c 包含了一份在虚拟机下安装测试的文档 xff0c 我们按照这个文档测试一下 VxWorks 6 8 3 43 VxWorks Workbench 3 2 3 43 VMware 16 1 2 43
  • 后浪小萌新Python --- 类中的属性

    一 什么是属性 我们通过类中的属性来保存类相关的属性 二 属性的分类 类中的属性分为两种 xff1a 类属性和对象属性 类属性 类的字段 a 定义 xff1a 直接定义在类中的变量就是类属性 b 使用 xff1a 类 属性 c 什么时候用
  • 业务架构的定义、特性和方法

    引言 业务架构一般不被开发重视 xff0c 开发人员喜欢追求新技术 xff0c 而技术是服务于业务的 xff0c 现在没有一项技术是自娱自乐的 xff0c 一定要支撑业务 xff0c 否则没有场景 设计好业务架构要考虑的方面比较多 xff0
  • VMware虚拟机扩展磁盘空间Ubuntu(超简单)

    一 简介 在平时使用时 xff0c 会遇到安装的虚拟机磁盘空间不足 的情况 此时需要给系统扩展磁盘空间 网上的很多教程都是输入一堆命令 xff0c 申请 分配 初始化 挂载等等特别麻烦 今天介绍一个最简单 最实用 的方法 二 实操 先进入r
  • Ubuntu 安装git及git命令

    1 检查git是否已经安装 xff0c 输入git version命令即可 xff0c 如果没有显示版本号表示没有安装git 2 安装git sudo apt get install git 3 配置git全局环境 git config g
  • Bad method handle type 7异常解决

    在利用androidx版本写demo时 xff0c 在添加了一些依赖后 xff0c 遇到了java lang ClassNotFoundExceptionbug xff0c 这就很奇怪了 xff0c 我就添加rxjava3的依赖 xff0c
  • linux防火墙添加端口

    iptables版 iptables nL line number vi etc sysconfig iptables 添加以下语句 A RH Firewall 1 INPUT p tcp m state state NEW m tcp d
  • 如何在webstorm使用eslint检查代码规范

    一 安装esLint xff08 一 xff09 打开项目代码 xff0c 进入terminal xff08 二 xff09 安装esLint 1 安装esLint npm install eslint span class token o
  • VUE基本格式

    96 VUE基本格式 lt template gt lt div gt lt div gt lt template gt lt script gt export default beforeCreate function data retu
  • Decode Ways 解码方法

    一条包含字母 A Z 的消息通过以下方式进行了编码 xff1a 39 A 39 gt 1 39 B 39 gt 2 39 Z 39 gt 26 给定一个只包含数字的非空 字符串 xff0c 请计算解码方法的总数 示例 1 输入 34 12
  • CAS单点登录6 - 服务端自定义返回的用户信息

    原理 返回的用户信息是在deployerConfigContext xml中的配置的 既然想自定义返回的用户信息 xff0c 那么继承org jasig services persondir support StubPersonAttrib