feat(auth): 添加CAS单点登录功能

- 配置开发和生产环境的CAS登录URL和登出URL
- 新增CacheHelper缓存工具类用于缓存操作
- 创建LideeUserDto用户数据传输对象
- 在SecurityConfig中允许CAS登录和登出接口匿名访问
- 添加SysLoginController中的logincas和outlogcas接口
- 实现SysLoginService中的CAS登录验证和登出逻辑
- 集成HttpUtils进行CAS服务器通信验证

Signed-off-by: NewName <1048783178@qq.com>
This commit is contained in:
NewName
2026-03-27 16:18:58 +08:00
parent 4dbe762e2c
commit 71a3807825
7 changed files with 208 additions and 2 deletions

View File

@@ -115,7 +115,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/register", "/captchaImage","/iot/tool/register","/iot/tool/ntp",
"/iot/tool/mqtt/auth","/iot/tool/mqtt/authv5","/iot/tool/mqtt/webhook","/iot/tool/mqtt/webhookv5","/auth/**/**",
"/wechat/mobileLogin", "/wechat/miniLogin", "/wechat/wxBind/callback").permitAll()
"/wechat/mobileLogin", "/wechat/miniLogin", "/wechat/wxBind/callback","/logincas","/outlogcas").permitAll()
.antMatchers("/zlmhook/**").permitAll()
//.antMatchers("/sip/player/getBigScreenUrl/**").permitAll()
.antMatchers("/ruleengine/rulemanager/**").permitAll()

View File

@@ -1,9 +1,13 @@
package iot.lidee.framework.web.service;
import com.alibaba.fastjson2.JSONObject;
import iot.lidee.common.constant.CacheConstants;
import iot.lidee.common.constant.Constants;
import iot.lidee.common.constant.LideeConstant;
import iot.lidee.common.core.cache.CacheHelper;
import iot.lidee.common.core.domain.entity.SysDept;
import iot.lidee.common.core.domain.entity.SysUser;
import iot.lidee.common.core.domain.model.LideeUserDto;
import iot.lidee.common.core.domain.model.LoginUser;
import iot.lidee.common.core.redis.RedisCache;
import iot.lidee.common.enums.UserStatus;
@@ -15,6 +19,7 @@ import iot.lidee.common.utils.DateUtils;
import iot.lidee.common.utils.MessageUtils;
import iot.lidee.common.utils.ServletUtils;
import iot.lidee.common.utils.StringUtils;
import iot.lidee.common.utils.http.HttpUtils;
import iot.lidee.common.utils.ip.IpUtils;
import iot.lidee.framework.manager.AsyncManager;
import iot.lidee.framework.manager.factory.AsyncFactory;
@@ -22,7 +27,9 @@ import iot.lidee.framework.security.context.AuthenticationContextHolder;
import iot.lidee.system.service.ISysConfigService;
import iot.lidee.system.service.ISysDeptService;
import iot.lidee.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -37,6 +44,7 @@ import javax.annotation.Resource;
*
* @author ruoyi
*/
@Slf4j
@Component
public class SysLoginService {
@Autowired
@@ -62,6 +70,18 @@ public class SysLoginService {
@Resource
private ISysDeptService sysDeptService;
@Resource
private SysPermissionService permissionService;
@Resource
private CacheHelper cacheHelper;
@Value("${cas.loginurl:}")
private String casLoginUrl;
@Value("${cas.outlogouturl:}")
private String casoutlogouturl;
/**
* 登录验证
*
@@ -262,4 +282,77 @@ public class SysLoginService {
// 生成token
return tokenService.createToken(loginUser);
}
public String logincas(LideeUserDto dto) {
String loginName = validateCasToken(dto.getLoginName());
if (StringUtils.isNull(loginName)) {
throw new ServiceException("该用户不存在!");
}
SysUser accessUser = userService.selectUserByUserName(loginName);
if (null == accessUser) {
throw new ServiceException("该用户不存在!");
}
Long deptId = accessUser.getDeptId();
SysDept sysDept = null;
if (deptId != null) {
sysDept = sysDeptService.selectDeptById(deptId);
}
LoginUser loginUser = new LoginUser(
accessUser.getUserId(),
deptId,
null,
accessUser,
permissionService.getMenuPermission(accessUser)
);
if (sysDept != null) {
loginUser.setDeptUserId(sysDept.getDeptUserId());
}
redisCache.setCacheObject(loginName + "_cas", dto.getLoginName());
recordLoginInfo(loginUser.getUserId());
AsyncManager.me().execute(AsyncFactory.recordLogininfor(
accessUser.getUserName(),
Constants.LOGIN_SUCCESS,
MessageUtils.message("user.login.success")
));
return tokenService.createToken(loginUser);
}
private String validateCasToken(String refreshToken) {
String url = casLoginUrl + "?refreshToken=" + refreshToken;
String response = HttpUtils.sendPost(url, refreshToken);
if (StringUtils.isEmpty(response)) {
return "";
}
try {
JSONObject jsonObject = JSONObject.parseObject(response);
if (jsonObject != null && jsonObject.getInteger("code") == 0) {
JSONObject data = jsonObject.getJSONObject("data");
if (data != null) {
return data.getString("username");
}
}
} catch (Exception e) {
SysLoginService.log.error("CAS 验证失败", e);
}
return "";
}
public void outlogcas(LideeUserDto dto) {
String token= redisCache.getCacheObject(dto.getLoginName()+"_cas");
String url = casoutlogouturl+"?refreshToken="+ token;
String response = HttpUtils.sendPost(url, token);
}
}