某J 集成 cas5.3res api登录

在学习一个开源项目是时集成了cas,但文档过于简单,研究了两天这次记录做个补充

1.下载cas项目

 GitHub - apereo/cas-overlay-template at 5.3

2.编译

解压zip,命令行进去,执行mvn clean package
结束之后会出现 target 文件夹,里面有一个cas.war包,这个cas.war包就是我们要运行的程序。

环境介绍
节点                                                                            服务名
http://localhost:3100/                                                    某J前端

http://localhost:9999/sys/cas/client/validateLogin 某J后端二次验证用户并赋予token登信息
http://cas.test.com:8888/cas                                         CAS服务端(域名自己配置host文件)
http://localhost:9999/sys/casLogin                                rest-client(认证服务)


cas怎么调用cas认证服务的  cas.authn.rest.uri=http://localhost:9999/sys/casLogin

当用户点击登录后,cas会发送post请求到http://rest.cas.com:8083/login并且把用户信息以"用户名:密码"进行Base64编码放在authorization请求头中。
若输入用户名密码为:admin/123456;那么请求头包括:
authorization=Basic Base64(admin+MD5(123))
那么发送后客户端必须响应一下数据,cas明确规定如下:
    ● cas 服务端会通过post请求,并且把用户信息以”用户名:密码”进行Base64编码放在authorization请求头中
    ● 200状态码:并且格式为
{“@class”:”org.apereo.cas.authentication.principal.SimplePrincipal”,”id”:”casuser”,”attributes”:{}}是成功的
    ● 403状态码:用户不可用
    ● 404状态码:账号不存在
    ● 423状态码:账户被锁定
    ● 428状态码:过期
    ● 其他登录失败

某j整体思路

3.配置

修改cas.war中的cas\WEB-INF\classes配置文件

cas服务端配置
pom.xml添加以下rest依赖
 

<dependency>
    <groupId>org.apereo.cas</groupId>
    <artifactId>cas-server-support-rest-authentication</artifactId>
    <version>${cas.version}</version>
</dependency>


 
application.properties添加如下配置

 

#是否开启json识别功能,默认为false
cas.serviceRegistry.initFromJson=true
#忽略https安全协议,使用 HTTP 协议
cas.tgc.secure=false
cas.authn.rest.uri=http://localhost:9999/sys/casLogin

兼容http请求:

修改cas\WEB-INF\classes\services\HTTPSandIMAPS-10000001.json 加入http

{
  "@class" : "org.apereo.cas.services.RegexRegisteredService",
  "serviceId" : "^(https|http|imaps)://.*",
  "name" : "HTTPS and IMAPS",
  "id" : 10000001,
  "description" : "This service definition authorizes all application urls that support HTTPS and IMAPS protocols.",
  "evaluationOrder" : 10000
}


#如果密码有加密,打开下面配置,我的是明文

#cas.authn.rest.passwordEncoder.type=DEFAULT
#cas.authn.rest.passwordEncoder.characterEncoding=UTF-8
#cas.authn.rest.passwordEncoder.encodingAlgorithm=MD5
 

4.启动cas服务

把cas.war放到tomcat里启动就行

5.rest-client接口代码

实体CasUser

package org.jeecg.modules.system.entity;


import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;

import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: zfq
 * @date: 2024
 * @description: cas-rest返回cas服务端信息
 */
public class CasUser {

    @JsonProperty("id")
    @NotNull
    private String username;

    /**
     * 需要返回实现org.apereo.cas.authentication.principal.Principal的类名接口
     */
    @JsonProperty("@class")
    private String clazz = "org.apereo.cas.authentication.principal.SimplePrincipal";


    @JsonProperty("attributes")
    private Map<String, Object> attributes = new HashMap<>();

    @JsonIgnore
    @NotNull
    private String password;

    /**
     * 用户状态,根据状态判断是否可用
     */
    @JsonIgnore
    private String state;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

    public Map<String, Object> getAttributes() {
        return attributes;
    }

    public void setAttributes(Map<String, Object> attributes) {
        this.attributes = attributes;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    @JsonIgnore
    public CasUser addAttribute(String key, Object val) {
        getAttributes().put(key, val);
        return this;
    }
}

接口casLogin

/**
	 * 1. cas 服务端会通过post请求,并且把用户信息以"用户名:密码"进行Base64编码放在authorization请求头中
	 * 2. 返回200状态码并且格式为{"@class":"org.apereo.cas.authentication.principal.SimplePrincipal","id":"casuser","attributes":{}} 是成功的
	 * 2. 返回状态码403用户不可用;404账号不存在;423账户被锁定;428过期;其他登录失败
	 * @param httpHeaders
	 * @return
	 */
	@RequestMapping("/casLogin")
	public Object login(@RequestHeader HttpHeaders httpHeaders){
		CasUser casUser=new CasUser();
		try {
			UserTemp userTemp = obtainUserFormHeader(httpHeaders);
			//尝试查找用户库是否存在

			LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
			queryWrapper.eq(SysUser::getUsername,userTemp.username);
			SysUser user = sysUserService.getOne(queryWrapper);

			String userpassword = PasswordUtil.encrypt(user.getUsername(), userTemp.password, user.getSalt());
			//{“@class”:”org.apereo.cas.authentication.principal.SimplePrincipal”,”id”:”casuser”,”attributes”:{}}是成功的
			casUser.setUsername(user.getUsername());

			if (user != null) {
				if (!user.getPassword().equals(userpassword)) {
					//密码不匹配
					return new ResponseEntity(HttpStatus.BAD_REQUEST);
				}
				if (!"1".equals(user.getStatus())) {// 状态(1:正常  2:冻结 )
					//用户已锁定
					return new ResponseEntity(HttpStatus.LOCKED);
				}

			} else {
				//不存在 404
				return new ResponseEntity(HttpStatus.NOT_FOUND);
			}
		} catch (UnsupportedEncodingException e) {
			new ResponseEntity(HttpStatus.BAD_REQUEST);
		}
		//成功返回json
		return casUser;
	}

	/**
	 * This allows the CAS server to reach to a remote REST endpoint via a POST for verification of credentials.
	 * Credentials are passed via an Authorization header whose value is Basic XYZ where XYZ is a Base64 encoded version of the credentials.
	 * @param httpHeaders
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private UserTemp obtainUserFormHeader(HttpHeaders httpHeaders) throws UnsupportedEncodingException {

		//cas服务端会通过把用户信息放在请求头authorization中,并且通过Basic认证方式加密
		String authorization = httpHeaders.getFirst("authorization");
		if(StringUtils.isEmpty(authorization)){
			return null;
		}

		String baseCredentials = authorization.split(" ")[1];
		//用户名:密码
		String usernamePassword = new String(Base64Utils.decodeFromString(baseCredentials), "UTF-8");
		String[] credentials = usernamePassword.split(":");

		return new UserTemp(credentials[0], credentials[1]);
	}

	/**
	 * 从请求头中获取用户名和密码
	 */
	private class UserTemp {
		private String username;
		private String password;

		public UserTemp(String username, String password) {
			this.username = username;
			this.password = password;
		}
	}

某J validateLogin二次验证用户并赋予token(不是该框架的可以忽略,是的话官方有代码)

package org.jeecg.modules.cas.controller;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.cas.util.CasServiceUtil;
import org.jeecg.modules.cas.util.XmlUtils;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;

import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * CAS单点登录客户端登录认证
 * </p>
 *
 * @Author zfq
 * @since 2023-12-20
 */
@Slf4j
@RestController
@RequestMapping("/sys/cas/client")
public class CasClientController {

	@Autowired
	private ISysUserService sysUserService;
	@Autowired
    private ISysDepartService sysDepartService;
	@Autowired
    private RedisUtil redisUtil;
	
	@Value("${cas.prefixUrl}")
    private String prefixUrl;
	
	
	@GetMapping("/validateLogin")
	public Object validateLogin(@RequestParam(name="ticket") String ticket,
								@RequestParam(name="service") String service,
								HttpServletRequest request,
								HttpServletResponse response) throws Exception {
		Result<JSONObject> result = new Result<JSONObject>();
		log.info("Rest api login.");
		try {
			String validateUrl = prefixUrl+"/p3/serviceValidate";
			String res = CasServiceUtil.getStValidate(validateUrl, ticket, service);
			log.info("res."+res);
			final String error = XmlUtils.getTextForElement(res, "authenticationFailure");
			if(StringUtils.isNotEmpty(error)) {
				throw new Exception(error);
			}
			final String principal = XmlUtils.getTextForElement(res, "user");
			if (StringUtils.isEmpty(principal)) {
	            throw new Exception("No principal was found in the response from the CAS server.");
	        }
			log.info("-------token----username---"+principal);
		    //1. 校验用户是否有效
	  		SysUser sysUser = sysUserService.getUserByName(principal);
	  		result = sysUserService.checkUserIsEffective(sysUser);
	  		if(!result.isSuccess()) {
	  			return result;
	  		}
	 		String token = JwtUtil.sign(sysUser.getUsername(), sysUser.getPassword());
	 		// 设置超时时间
	 		redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
	 		redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000);

	 		//获取用户部门信息
			JSONObject obj = new JSONObject();
			List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
			obj.put("departs", departs);
			if (departs == null || departs.size() == 0) {
				obj.put("multi_depart", 0);
			} else if (departs.size() == 1) {
				sysUserService.updateUserDepart(principal, departs.get(0).getOrgCode(),null);
				obj.put("multi_depart", 1);
			} else {
				obj.put("multi_depart", 2);
			}
			obj.put("token", token);
			obj.put("userInfo", sysUser);
			result.setResult(obj);
			result.success("登录成功");
	  		
		} catch (Exception e) {
			//e.printStackTrace();
			result.error500(e.getMessage());
		}
		return new HttpEntity<>(result);
	}

	
}

6.某J前后端配置

  • 前端vue项目对接CAS

某J 前端3.0.0以后只默认集成SSO所有要的代码,只需需修改环境配置文件即可开启SSO

打开.env文件

#单点服务端地址
VITE_GLOBE_APP_CAS_BASE_URL=http://cas.test.com:8443/cas

# 是否开启单点登录
VITE_GLOB_APP_OPEN_SSO = false

复制

VITE_GLOB_APP_OPEN_SSO =true 即代表开启SSO登录

=============================

  • 后端boot修改yml配置
cas:
  # 配置CAS服务地址,cas为工程目录,部署到ROOT目录下http://cas.test.com:8443即可
  prefixUrl: http://cas.test.com:8443/cas 

6.最后启动各个服务访问前端:

一会跳到cas界面

输入完账号密码跳到首页但没内容,某j的bug感觉是

刷新完正常

参考博客:

cas5.3.2单点登录-rest认证(十二)_cas 调用其它接口认证-CSDN博客 这家写的cas真不错,十几篇成体系,比某些收费的都要好

https://www.cnblogs.com/youqc/p/14861455.html 这家的主要是入门免证书,htpp配置等

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/476324.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android14 - Framework- Configuration的创建和更新

本文描述从启动一个新进程的Activity起&#xff0c;Framwork层Configuration的创建和传导过程。 首先&#xff0c;我们知道所有的Window容器都继承于WindowContainer&#xff0c;而WindowContainer本身是ConfigurationContainer的子类。于此同时&#xff0c;WindowProcessContr…

[NOIP1998 提高组] 拼数

[NOIP1998 提高组] 拼数 题目描述 设有 n n n 个正整数 a 1 … a n a_1 \dots a_n a1​…an​&#xff0c;将它们联接成一排&#xff0c;相邻数字首尾相接&#xff0c;组成一个最大的整数。 输入格式 第一行有一个整数&#xff0c;表示数字个数 n n n。 第二行有 n n …

【Vue3遇见的问题】创建vue3的项目使用vscode打开后项目的app.vue里面存在爆红

出现的问题 直接上上问题:问题的图片如下: 解决方法 解决效果 补充 因为vetur的插件禁用了 所以需要一个新插件来 这里发现的官网推荐的插件 也就是volar 他两是一样的

各位老板,你需要的工厂数字孪生可视化库在这

各位老板是不是很喜欢下面这种有逼格的大屏,下面介绍一下怎么实现的,保证有所收获。 Cesium是一个开源的WebGL JavaScript库&#xff0c;用于创建高性能的三维地球、地图和虚拟环境。它支持在浏览器中实现高质量的地球模拟&#xff0c;同时提供了丰富的功能特点&#xff0c;使得…

【Linux进程的状态】

目录 看Linux源码中的说法 如何查看进程状态&#xff1f; 各个状态的关系 僵尸进程 举个栗子 现象 僵尸进程的危害 孤儿进程 举个栗子 现象 进程的优先级 基本概念 为什么要有进程优先级&#xff1f; 查看系统进程 进程的大致属性 进程优先级vs进程的权限 Linu…

AI基础知识(4)--贝叶斯分类器

1.什么是贝叶斯判定准则&#xff08;Bayes decision rule&#xff09;&#xff1f;什么是贝叶斯最优分类器&#xff08;Bayes optimal classifier&#xff09;&#xff1f; 贝叶斯判定准则&#xff1a;为最小化总体风险&#xff0c;只需在每个样本上选择那个能使条件风险最小的…

用 Open-Sora 高效创作视频,让创意触手可及

近年来&#xff0c;视频内容以爆炸式增长席卷了我们的生活。从短视频平台到直播带货&#xff0c;视频正成为人们获取信息和娱乐的主要方式。然而&#xff0c;传统视频制作流程往往耗时费力&#xff0c;对于普通用户来说门槛较高。 为了降低视频创作门槛&#xff0c;让更多人享…

Git的 .gitignore文件及标签使用

Git的 .gitignore文件及标签使用 什么是.gitignoregit check-ignore -v 文件名 查看.gitignore里面什么内容忽略了该文件 git add -f [filename] 强制添加把指定文件排除在 .gitignore 规则外的写法给命令配置别名标签创建标签git tag [name] 创建标签git tag 列出所有标签git …

RESNET的复现pytorch版本

RESNET的复现pytorch版本 使用的数据为Object_102_CaDataset&#xff0c;可以在网上下载&#xff0c;也可以在评论区问。 RESNET模型的亮点 1.提出了残差模块。 2.使用Batch Normalization加速训练 3.残差网络&#xff1a;易于收敛&#xff0c;很好的解决了退化问题&#…

真实数据!一张切片实现101种蛋白的超多重空间单细胞原位成像

头颈鳞状细胞癌 (HNSCC) 是第七大常见癌症。免疫检查点抑制剂 (ICIs) 在治疗复发/转移病例方面显示出良好前景&#xff0c;约30%的患者可获得持久获益。但是目前反映HNSCC肿瘤微环境 (TME) 特征的生物标志物有限&#xff0c;需要更深入的组织表征分析。因此&#xff0c;需要新的…

linux查看cpu/内存/磁盘利用率

1、cpu 命令&#xff1a; top 2、内存 命令&#xff1a; free -h 3、磁盘 命令&#xff1a; df -h

《操作系统真相还原》读书笔记九:用c编写内核

用c语言先编写一个死循环 main.c int main(void) {while(1);return 0; }编译该文件 gcc -c -o main.o main.c-- Ttext参数表示起始虚拟地址为0xc0001500 -e参数表示程序入口地址 ld main.o -Ttext 0xc0001500 -e main -o kernel.bin-- 将kernel.bin写入第9个扇区 dd if/ho…

十九、网络编程

目录 一、什么是网络编程二、网络编程三要素2.1 IP2.2 InetAddress的使用2.3 端口号2.4 协议 三、UDP通信程序3.1 发送数据3.2 接收数据3.3 练习 四、UDP的三种通信方式五、TCP的通信程序六、三次握手和四次挥手七、练习7.1 TCP通信练习1——多发多收7.2 TCP通信练习2——接收和…

Cookie使用

文章目录 一、Cookie基本使用1、发送Cookie2、获取Cookie 二、Cookie原理三、Cookie使用细节 一、Cookie基本使用 1、发送Cookie package com.itheima.web.cookie;import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.I…

82.删除排序链表中的重复元素II

给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,3,4,4,5] 输出&#xff1a;[1,2,5]示例 2&#xff1a; 输入&#xff1a;head [1,1,1,2…

【OJ比赛日历】快周末了,不来一场比赛吗? #03.23-03.29 #16场

CompHub[1] 实时聚合多平台的数据类(Kaggle、天池…)和OJ类(Leetcode、牛客…&#xff09;比赛。本账号会推送最新的比赛消息&#xff0c;欢迎关注&#xff01; 以下信息仅供参考&#xff0c;以比赛官网为准 目录 2024-03-23&#xff08;周六&#xff09; #7场比赛2024-03-24…

高级数据结构 <AVL树>

本文已收录至《数据结构(C/C语言)》专栏&#xff01; 作者&#xff1a;ARMCSKGT 目录 前言正文AVL树的性质AVL树的定义AVL树的插入函数左单旋右单旋右左双旋左右双旋 检验AVL树的合法性关于AVL树 最后 前言 前面我们学习了二叉树&#xff0c;普通的二叉树没有任何特殊性质&…

C语言易错知识点:二级指针、数组指针、函数指针

指针在C语言中非常关键&#xff0c;除开一些常见的指针用法&#xff0c;还有一些可能会比较生疏&#xff0c;但有时却也必不可少&#xff0c;本文章整理了一些易错知识点&#xff0c;希望能有所帮助&#xff01; 1.二级指针&#xff1a; parr是一个指针数组&#xff0c;其中每…

GEE遥感云大数据林业应用典型案例及GPT模型应用

近年来遥感技术得到了突飞猛进的发展&#xff0c;航天、航空、临近空间等多遥感平台不断增加&#xff0c;数据的空间、时间、光谱分辨率不断提高&#xff0c;数据量猛增&#xff0c;遥感数据已经越来越具有大数据特征。遥感大数据的出现为相关研究提供了前所未有的机遇&#xf…

数据结构:初识树和二叉树

目前主流的方式是左孩子右兄弟表示法 我们的文件系统就是一个树 以上就是树的概念&#xff0c;我们今天还要来学习一种从树演变的重要的结构&#xff1a;二叉树 顾名思义二叉树就是一个结点最多有两个子树。 其中我们还要了解满二叉树和完全二叉树的概念 注意我们的完全二叉…