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:
@@ -1,14 +1,17 @@
|
||||
package iot.lidee.web.controller.system;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import iot.lidee.common.core.domain.model.LideeUserDto;
|
||||
import iot.lidee.system.domain.AppPreferences;
|
||||
import iot.lidee.system.service.IAppPreferencesService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
@@ -69,6 +72,29 @@ public class SysLoginController
|
||||
return ajax;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 登录方法
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
@PostMapping({"/logincas"})
|
||||
public AjaxResult logincas(@RequestBody @Validated LideeUserDto dto) {
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
// 生成令牌
|
||||
String token = loginService.logincas(dto);
|
||||
ajax.put(Constants.TOKEN, token);
|
||||
return ajax;
|
||||
}
|
||||
|
||||
@PostMapping({"/outlogcas"})
|
||||
public AjaxResult outlogcas(@RequestBody @Validated LideeUserDto dto){
|
||||
// 生成令牌
|
||||
loginService.outlogcas(dto);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
|
||||
@@ -147,4 +147,9 @@ logging:
|
||||
swagger:
|
||||
enabled: true # 是否开启swagger
|
||||
pathMapping: /dev-api # 请求前缀
|
||||
cas:
|
||||
loginurl: http://127.0.0.1:48080/admin-api/system/auth/user-info
|
||||
outlogouturl: http://127.0.0.1:48080/admin-api/system/auth/logout-client
|
||||
# loginurl: http://192.168.1.241/admin-api/system/auth/user-info
|
||||
# outlogouturl: http://192.168.1.241/admin-api/system/auth/logout-client
|
||||
|
||||
|
||||
@@ -147,4 +147,9 @@ logging:
|
||||
swagger:
|
||||
enabled: true # 是否开启swagger
|
||||
pathMapping: /dev-api # 请求前缀
|
||||
cas:
|
||||
# loginurl: http://127.0.0.1:48080/admin-api/system/auth/user-info
|
||||
# outlogouturl: http://127.0.0.1:48080/admin-api/system/auth/logout-client
|
||||
loginurl: http://192.168.1.241/admin-api/system/auth/user-info
|
||||
outlogouturl: http://192.168.1.241/admin-api/system/auth/logout-client
|
||||
|
||||
|
||||
50
lidee-common/src/main/java/iot/lidee/common/core/cache/CacheHelper.java
vendored
Normal file
50
lidee-common/src/main/java/iot/lidee/common/core/cache/CacheHelper.java
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
package iot.lidee.common.core.cache;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
public class CacheHelper {
|
||||
|
||||
/**
|
||||
* 获取指定key的String类型缓存
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public String stringGet(String key) {
|
||||
return null;
|
||||
}
|
||||
Map<String,String> stringMultiGet(List<String> keys) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置指定key的String类型缓存
|
||||
* @param key
|
||||
* @param value 缓存值
|
||||
* @return
|
||||
*/
|
||||
public void stringSet(String key, String value) {
|
||||
|
||||
}
|
||||
/**
|
||||
* 设置指定key的String类型缓存,包含过期时间
|
||||
* @param key
|
||||
* @param value
|
||||
* @param seconds
|
||||
*/
|
||||
public void stringSetExpire(String key, String value, long seconds) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否存在指定KEY
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public boolean exist(String key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package iot.lidee.common.core.domain.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class LideeUserDto {
|
||||
|
||||
/** 登录名*/
|
||||
@NotBlank
|
||||
private String loginName;
|
||||
|
||||
/** 密码*/
|
||||
@NotBlank
|
||||
private String password;
|
||||
|
||||
/** 真实用户 */
|
||||
private String realName;
|
||||
|
||||
/** 登录成功后的 */
|
||||
private String token;
|
||||
|
||||
/** 用户所拥有的权限合集 */
|
||||
private List<String> authorities;
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user