若依微服务集成CAS,实现单点登录

若依(RuoYi)微服务是一款基于Spring Cloud Alibaba开发的企业级微服务框架,采用前后端分离方式,使用了常用的微服务组件,如Feign、Nacos、Sentinel、Seata等,提供了丰富的微服务治理功能,如服务注册、发现、路由、负载均衡、熔断降级、限流等。借助若依微服务框架可以让我们快速构建起一个高效、可靠、可扩展的分布式系统,提高了开发效率和系统性能。

借助Spring Cloud Alibaba,若依微服务框架完成了后端的微服务改造,但是前端仍是一个单体服务,随着业务的增长,前端必然变的庞大、臃肿,不可避免的需要对前端进行拆分,然而前端拆分后面临的一个问题是登录信息如何同步?登录信息是以token存储在cookie中的,无法共享。

为了解决前端登录信息同步的问题,这里考虑通过集成CAS的方式,实现统一认证。

研究了若依微服务的认证功能后发现,若依微服务的认证并未使用Spring Security,仅仅使用了Spring Security的加密功能,无法直接套用若依分离版集成CAS的方式。所以通过结合分离版集成思路及CAS官方集成方法完成若依微服务集成CAS。集成方法如下:

1、添加CAS依赖

在auth模块中添加cas依赖:

<!-- Cas Core -->
<dependency><groupId>org.jasig.cas.client</groupId><artifactId>cas-client-core</artifactId><version>3.6.4</version>
</dependency>

2、修改配置文件

在nacos中修改ruoyi-auth-dev.yml(或直接修改auth模块下bootstrap.yml文件),增加cas配置:

cas:enable: trueserver:url:prefix: http://127.0.0.1:8888/caslogin: http://127.0.0.1:8888/cas/loginclient:url: http://127.0.0.1:8080/auth

3、修改Constants.java

修改common-core模块下
com.ruoyi.common.core.constant.Constants.java,增加CAS认证成功标识:

/*** CAS登录成功后的后台标识**/
public static final String CAS_TOKEN = "cas_token";/*** CAS登录成功后的前台Cookie的Key**/
public static final String WEB_TOKEN_KEY = "Cloud-Token";/*** CAS登录成功后的前台Cookie的Expires-In**/
public static final String WEB_TOKEN_EXPIRES = "Cloud-Expires-In";

4、添加CasProperties.java

在auth模块中添加CasProperties.java文件,获取CAS配置信息:

package com.ruoyi.auth.cas.config.properties;import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;/*** @author LuoFei* @className: CasProperty* @projectName RuoYi-Cloud-master* @description: cas配置参数* @date 2022/7/21 10:11**/
@Configuration
@RefreshScope
public class CasProperties {@Value("${cas.enable}")private Boolean enabled;@Value("${cas.server.url.prefix}")private String casServerUrlPrefix;@Value("${cas.server.url.login}")private String casServerLoginUrl;@Value("${cas.client.url}")private String serverName;public Boolean getEnabled() {return enabled;}public void setEnabled(Boolean enabled) {this.enabled = enabled;}public String getCasServerUrlPrefix() {return casServerUrlPrefix;}public void setCasServerUrlPrefix(String casServerUrlPrefix) {this.casServerUrlPrefix = casServerUrlPrefix;}public String getCasServerLoginUrl() {return casServerLoginUrl;}public void setCasServerLoginUrl(String casServerLoginUrl) {this.casServerLoginUrl = casServerLoginUrl;}public String getServerName() {return serverName;}public void setServerName(String serverName) {this.serverName = serverName;}
}

5、添加NoCasFilter.java

在auth模块中添加NoCasFilter.java文件,在未启用CAS时直接放行:

package com.ruoyi.auth.cas.filter;import javax.servlet.*;
import java.io.IOException;/*** @author LuoFei* @className: NoCasFilter* @projectName RuoYi-Cloud-master* @description: 单点登录停用辅助过滤器* @date 2022/7/21 11:19**/
public final class NoCasFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {filterChain.doFilter(request, response);}
}

6、 添加
CustomSessionMappingStorage.java

在auth模块中添加
CustomSessionMappingStorage.java文件,实现单点登出:

package com.ruoyi.auth.cas.storage;import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.security.service.TokenService;
import org.apache.catalina.session.StandardSessionFacade;
import org.jasig.cas.client.session.SessionMappingStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;/*** @author LuoFei* @className: CustomSessionMappingStorage* @projectName RuoYi-Vue-master* @description: 单点登录-前后端分离-单点登出删除token* @date 2022/4/28 12:56**/
@Component
public class CustomSessionMappingStorage implements SessionMappingStorage {private final Map<String, HttpSession> MANAGED_SESSIONS = new HashMap();private final Map<String, String> ID_TO_SESSION_KEY_MAPPING = new HashMap();private final Logger logger = LoggerFactory.getLogger(this.getClass());@Autowiredprivate TokenService tokenService;public CustomSessionMappingStorage() {}@Overridepublic synchronized void addSessionById(String mappingId, HttpSession session) {this.ID_TO_SESSION_KEY_MAPPING.put(session.getId(), mappingId);this.MANAGED_SESSIONS.put(mappingId, session);}@Overridepublic synchronized void removeBySessionById(String sessionId) {this.logger.debug("Attempting to remove Session=[{}]", sessionId);String key = (String)this.ID_TO_SESSION_KEY_MAPPING.get(sessionId);if (this.logger.isDebugEnabled()) {if (key != null) {this.logger.debug("Found mapping for session.  Session Removed.");} else {this.logger.debug("No mapping for session found.  Ignoring.");}}this.MANAGED_SESSIONS.remove(key);this.ID_TO_SESSION_KEY_MAPPING.remove(sessionId);}@Overridepublic synchronized HttpSession removeSessionByMappingId(String mappingId) {StandardSessionFacade session = (StandardSessionFacade) this.MANAGED_SESSIONS.get(mappingId);if (session != null) {this.removeBySessionById(session.getId());try {String token = (String) session.getAttribute(Constants.CAS_TOKEN);tokenService.delLoginUser(token);} catch (IllegalStateException e) {this.logger.error("已成功登出");}}return session;}
}

7、增加casLogin方法

在auth模块的TokenController.java文件中添加casLogin方法,实现登录功能:

/*** 单点登录成功创建token* @param request* @param response* @throws IOException* @throws ServletException**/
@GetMapping("casLogin")
public void casLogin(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {String username = request.getRemoteUser();HttpSession httpSession = request.getSession();String url = request.getParameter("redirect");LoginUser userInfo = sysLoginService.login(username);Map<String, Object> token = tokenService.createToken(userInfo);Cookie tokenCookie = new Cookie(Constants.WEB_TOKEN_KEY, (String) token.get("access_token"));//必须设置path,否则获取不到cookietokenCookie.setPath("/");response.addCookie(tokenCookie);Cookie expiresCookie = new Cookie(Constants.WEB_TOKEN_EXPIRES, ((Long) token.get("expires_in")).toString());expiresCookie.setPath("/");response.addCookie(expiresCookie);//设置后端认证成功标识httpSession.setAttribute(Constants.CAS_TOKEN, token.get("access_token"));//登录成功后跳转到前端访问页面response.sendRedirect(url);
}

8、添加CasConfig.java文件

在auth模块中添加CasConfig.java文件:

package com.ruoyi.auth.cas.config;import com.ruoyi.auth.cas.config.properties.CasProperties;
import com.ruoyi.auth.cas.filter.NoCasFilter;
import com.ruoyi.auth.cas.storage.CustomSessionMappingStorage;
import org.jasig.cas.client.authentication.AuthenticationFilter;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.util.HttpServletRequestWrapperFilter;
import org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @author LuoFei* @className: CasConfig* @projectName RuoYi-Cloud-master* @description: TODO* @date 2022/7/19 14:17**/
@Configuration
public class CasConfig {@Autowiredprivate CasProperties casProperties;@Autowiredprivate CustomSessionMappingStorage customSessionMappingStorage;/*** 单点登出过滤器* @return**/@Beanpublic FilterRegistrationBean logoutFilter() {FilterRegistrationBean authenticationFilter = new FilterRegistrationBean<>();SingleSignOutFilter signOutFilter = new SingleSignOutFilter();signOutFilter.setSessionMappingStorage(customSessionMappingStorage);signOutFilter.setIgnoreInitConfiguration(true);authenticationFilter.setFilter(signOutFilter);authenticationFilter.addUrlPatterns("/*");Map<String, String> initParameters = new HashMap<>();initParameters.put("casServerUrlPrefix", casProperties.getCasServerUrlPrefix());authenticationFilter.setInitParameters(initParameters);authenticationFilter.setOrder(1);if (casProperties.getEnabled()) {return authenticationFilter;}return new FilterRegistrationBean<>(new NoCasFilter());}/*** 单点登录认证入口* @return**/@Beanpublic FilterRegistrationBean authenticationFilterRegistrationBean() {FilterRegistrationBean authenticationFilter = new FilterRegistrationBean();authenticationFilter.setFilter(new AuthenticationFilter());Map<String, String> initParameters = new HashMap<>();initParameters.put("casServerLoginUrl", casProperties.getCasServerLoginUrl());initParameters.put("serverName", casProperties.getServerName());authenticationFilter.setInitParameters(initParameters);authenticationFilter.setOrder(2);List<String> urlPatterns = new ArrayList<>();urlPatterns.add("/casLogin");authenticationFilter.setUrlPatterns(urlPatterns);if (casProperties.getEnabled()) {return authenticationFilter;}return new FilterRegistrationBean<>(new NoCasFilter());}/*** 单点登录验证入口* @return**/@Beanpublic FilterRegistrationBean validationFilterRegistrationBean() {FilterRegistrationBean authenticationFilter = new FilterRegistrationBean();authenticationFilter.setFilter(new Cas20ProxyReceivingTicketValidationFilter());Map<String, String> initParameters = new HashMap<>();initParameters.put("casServerUrlPrefix", casProperties.getCasServerUrlPrefix());initParameters.put("serverName", casProperties.getServerName());initParameters.put("encoding", "UTF-8");initParameters.put("useSession", "true");authenticationFilter.setInitParameters(initParameters);authenticationFilter.setOrder(3);List<String> urlPatterns = new ArrayList<>();urlPatterns.add("/*");authenticationFilter.setUrlPatterns(urlPatterns);if (casProperties.getEnabled()) {return authenticationFilter;}return new FilterRegistrationBean<>(new NoCasFilter());}/*** 单点登录获取登录信息* @return**/@Beanpublic FilterRegistrationBean casHttpServletRequestWrapperFilter() {FilterRegistrationBean authenticationFilter = new FilterRegistrationBean();authenticationFilter.setFilter(new HttpServletRequestWrapperFilter());authenticationFilter.setOrder(4);List<String> urlPatterns = new ArrayList<>();urlPatterns.add("/*");authenticationFilter.setUrlPatterns(urlPatterns);if (casProperties.getEnabled()) {return authenticationFilter;}return new FilterRegistrationBean<>(new NoCasFilter());}
}

9、放行casLogin请求

修改common-security模块中的WebMvcConfig.java,放行casLogin请求:

/** 不需要拦截地址 **/
public static final String[] excludeUrls = { "/casLogin", "/login", "/logout", "/refresh", "/register" };

修改nacos中ruoyi-gateway-dev.yml,在网关中放行casLogin请求:

# 不校验白名单ignore:whites:- /auth/casLogin- /auth/getToken- /auth/logout- /auth/login- /auth/register- /auth/updatePassword- /*/v2/api-docs- /csrf

至此,即完成若依微服务后端CAS集成工作。

若依微服务前端集成与分离版相同,请参考若依分离版集成CAS。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux查看命令总结

1.动态实时查找命令 使用以下命令的前提是需要在找到日志位置 tail -f server.log 实时展示日志末尾内容&#xff0c;默认最后10行,相当于增加参数 -n 10 tail -n filename; tail命令扩展 查看日志最后20行内容并实时更新日志 tail -f -n 20 server.log或者 tail -fn 20 ser…

【Python】代理池针对ip拦截破解

代理池是一种常见的反反爬虫技术&#xff0c;通过维护一组可用的代理服务器&#xff0c;来在被反爬虫限制的情况下&#xff0c;实现数据的爬取。但是&#xff0c;代理池本身也面临着被目标网站针对ip进行拦截的风险。 本文将详细介绍代理池针对ip拦截破解的方法&#xff0c;包含…

WPF的图形微语言

WPF的图形微语言 前言 WPF为定义几何图形增加了一种更简明的替换语法&#xff0c;通过该语法可用更少的标记表示详细的图形&#xff0c;这种语法称为图形微语言&#xff0c;并且由于应用于Path元素&#xff0c;也称为路径微语言。 示例 使用两条闭合路径创建了一个基本三角…

Avue-Card用法

1、基本属性 <template> <!-- 基础组件 --><basic-container><!-- <el-button clickexportHandle>导出</el-button> --><avue-crud//设置表格属性:option"option"//来存取页面的值v-model"form"//获取后台数据:dat…

蓝桥杯每日N题 (砝码称重)

大家好 我是寸铁 希望这篇题解对你有用&#xff0c;麻烦动动手指点个赞或关注&#xff0c;感谢您的关注 不清楚蓝桥杯考什么的点点下方&#x1f447; 考点秘籍 想背纯享模版的伙伴们点点下方&#x1f447; 蓝桥杯省一你一定不能错过的模板大全(第一期) 蓝桥杯省一你一定不…

Python入门教程 | Python简介和环境搭建

Python 简介 Python是一种高级编程语言&#xff0c;由荷兰人Guido van Rossum于1991年创建。它以其简单易学、可读性强和丰富的生态系统而受到广泛喜爱。它被广泛应用于各个领域&#xff0c;包括Web开发、科学计算、数据分析、人工智能等。 Python的特点 简洁易读&#xff1a…

回归预测 | MATLAB实现TSO-LSSVM金枪鱼群算法优化最小二乘支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现TSO-LSSVM金枪鱼群算法优化最小二乘支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现TSO-LSSVM金枪鱼群算法优化最小二乘支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&a…

免费开源的vue+express搭建的后台管理系统

此项目已开源 前端git地址&#xff1a;exp后台管理系统前端: exp后台管理系统前端 后端git地址&#xff1a;express后台管理系统: express后台管理系统 安装运行 npm i yarn i 前端: npm run dev | yarn dev 后端: npm run start | yarn start 主要技术栈 前端后端名称版本名…

大数据及软件教学与实验专业实训室建设方案

一 、系统概述 大数据及软件教学与实验大数据及软件教学与实验在现代教育中扮演重要角色&#xff0c;这方面的教学内容涵盖了大数据处理、数据分析、数据可视化和大数据应用等多个方面。以下是大数据及软件教学与实验的一般内容&#xff1a;1. 数据基础知识&#xff1a;教授学生…

redis--事务

redis事务 在Redis中&#xff0c;事务是一组原子性操作的集合&#xff0c;它们被一起执行&#xff0c;要么全部执行成功&#xff0c;要么全部回滚。虽然Redis的事务并不遵循传统数据库的ACID特性&#xff0c;但它仍然提供了一种将多个命令打包成一组执行的机制&#xff0c;适用…

Unity启动项目无反应的解决

文章首发见博客&#xff1a;https://mwhls.top/4803.html。 无图/格式错误/后续更新请见首发页。 更多更新请到mwhls.top查看 欢迎留言提问或批评建议&#xff0c;私信不回。 摘要&#xff1a;通过退还并重新载入许可证以解决Unity项目启动无反应问题。 场景 Unity Hub启动项目…

ZLMediakit-method ANNOUNCE failed: 401 Unauthorized

使用ffmpeg推流&#xff1a; nohup ffmpeg -stream_loop -1 -re -i "/usr/local/mp4/test.mp4" -vcodec h264 -acodec aac -f rtsp -rtsp_transport tcp rtsp://10.55.134.12/live/test &[rootlocalhost ~]# ffmpeg -stream_loop -1 -re -i "/usr/local/mp…

人脸老化预测(Python)

本次项目的文件 main.py主程序如下 导入必要的库和模块&#xff1a; 导入 TensorFlow 库以及自定义的 FaceAging 模块。导入操作系统库和参数解析库。 定义 str2bool 函数&#xff1a; 自定义函数用于将字符串转换为布尔值。 创建命令行参数解析器&#xff1a; 使用 argparse.A…

视觉学习(八)---zed调用yolov5之目标检测遇到的问题及解决

1.前言 zed调用yolov5进行目标检测时遇到的问题&#xff0c;记录下~~ 2.环境信息 开发板&#xff1a;Jetson Xviewer NX 摄像头&#xff1a; zed2系统&#xff1a;Ubuntu18.043.问题及解决 问题1&#xff1a; RuntimeError: cuDNN error: CUDNN_STATUS_MAPPING_ERROR 原因&…

【LINUX相关】生成随机数(srand、/dev/random 和 /dev/urandom )

目录 一、问题背景二、修改方法2.1 修改种子2.2 使用linux中的 /dev/urandom 生成随机数 三、/dev/random 和 /dev/urandom 的原理3.1 参考连接3.2 重难点总结3.2.1 生成随机数的原理3.2.2 随机数生成器的结构3.2.3 二者的区别和选择 四、在代码的使用方法 一、问题背景 在一个…

RabbitMq-2安装与配置

Rabbitmq的安装 1.上传资源 注意&#xff1a;rabbitmq的版本必须与erlang编译器的版本适配 2.安装依赖环境 //打开虚拟机 yum install build-essential openssl openssl-devel unixODBC unixODBC-devel make gcc gcc-c kernel-devel m4 ncurses-devel tk tc xz3.安装erlan…

理解docker命令

基础命令 帮助命令 docker --help&#xff08;帮助命令&#xff09; 用于获取某个命令的帮助信息 #命令帮助 docker 命令 --help 小技巧 换行符 \ 使用命令换符&#xff0c;可以让繁杂命令变得有条理 #命令换行&#xff0c;使用换行符 \ docker ... \... \ 镜像命令 d…

不含数字的webshell绕过

异或操作原理 1.首先我们得了解一下异或操作的原理 在php中&#xff0c;异或操作是两个二进制数相同时&#xff0c;异或(相同)为0&#xff0c;不同为1 举个例子 A的ASCII值是65&#xff0c;对应的二进制值是0100 0001 的ASCII值是96&#xff0c;对应的二进制值是 0110 000…

Android11 中 LED 使用-RK3568

文章目录 前言原理图设备树驱动前言 现在我们来学习点亮LED 原理图 然后对应在核心板原理图上查找 Working_LEDEN_H_GPIO0_B7,如下图所示: 那么我们只要控制 GPIO0_B7 即可控制 led 的亮灭。 设备树 leds: leds {compatible = "gpio-leds";work_led: work {gpi…

6-模板初步使用

官网: 中文版: 介绍-Jinja2中文文档 英文版: Template Designer Documentation — Jinja Documentation (2.11.x) 模板语法 1. 模板渲染 (1) app.py 准备数据 import jsonfrom flask import Flask,render_templateimport settingsapp Flask(__name__) app.config.from_obj…