重新修改了用户权限关联模块功能
This commit is contained in:
parent
90ca2cef2a
commit
c6e7657e62
@ -142,6 +142,13 @@
|
|||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>5.8.8</version>
|
<version>5.8.8</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- fastjson -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>1.2.83</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
import com.stdproject.entity.AppOptLog;
|
import com.stdproject.entity.AppOptLog;
|
||||||
import com.stdproject.service.IAppOptLogService;
|
import com.stdproject.service.IAppOptLogService;
|
||||||
import com.stdproject.utils.JwtUtils;
|
import com.stdproject.utils.JwtUtils;
|
||||||
|
import com.stdproject.utils.commonUtils;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
@ -92,8 +93,8 @@ public class OperationLogAspect {
|
|||||||
optLog.setModule(operationLog.module());
|
optLog.setModule(operationLog.module());
|
||||||
optLog.setDescription(operationLog.description());
|
optLog.setDescription(operationLog.description());
|
||||||
optLog.setMethod(request.getMethod() + " " + request.getRequestURI());
|
optLog.setMethod(request.getMethod() + " " + request.getRequestURI());
|
||||||
optLog.setRequestip(getIpAddress(request));
|
optLog.setRequestip(commonUtils.getIpAddress(request));
|
||||||
optLog.setBrowser(getBrowser(request));
|
optLog.setBrowser(commonUtils.getBrowser(request));
|
||||||
optLog.setLogtime(LocalDateTime.now());
|
optLog.setLogtime(LocalDateTime.now());
|
||||||
|
|
||||||
// 设置操作用户
|
// 设置操作用户
|
||||||
@ -150,32 +151,5 @@ public class OperationLogAspect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getBrowser(HttpServletRequest request) {
|
|
||||||
UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
|
|
||||||
Browser browser = userAgent.getBrowser();
|
|
||||||
return browser.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取客户端IP地址
|
|
||||||
*/
|
|
||||||
private String getIpAddress(HttpServletRequest request) {
|
|
||||||
String ip = request.getHeader("X-Forwarded-For");
|
|
||||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
|
||||||
ip = request.getHeader("Proxy-Client-IP");
|
|
||||||
}
|
|
||||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
|
||||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
|
||||||
}
|
|
||||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
|
||||||
ip = request.getHeader("HTTP_CLIENT_IP");
|
|
||||||
}
|
|
||||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
|
||||||
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
|
|
||||||
}
|
|
||||||
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
|
||||||
ip = request.getRemoteAddr();
|
|
||||||
}
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,197 +0,0 @@
|
|||||||
package com.stdproject.config;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
||||||
import com.stdproject.entity.User;
|
|
||||||
import com.stdproject.service.IMenuService;
|
|
||||||
import com.stdproject.service.IRoleService;
|
|
||||||
import com.stdproject.service.IUserService;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定义用户详情服务
|
|
||||||
* 实现Spring Security的UserDetailsService接口
|
|
||||||
*
|
|
||||||
* @author StdProject
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
|
||||||
public class CustomUserDetailsService implements UserDetailsService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IUserService appUserService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IRoleService appRoleService;
|
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IMenuService appMenuService;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
|
||||||
log.debug("加载用户信息: {}", username);
|
|
||||||
User appUser = appUserService.findByUsername(username);
|
|
||||||
if (appUser == null) {
|
|
||||||
log.warn("用户不存在: {}", username);
|
|
||||||
throw new UsernameNotFoundException("用户不存在: " + username);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查用户状态
|
|
||||||
if (!"1".equals(appUser.getStatus())) {
|
|
||||||
log.warn("用户已被禁用: {}", username);
|
|
||||||
throw new UsernameNotFoundException("用户已被禁用: " + username);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建用户权限
|
|
||||||
Collection<GrantedAuthority> authorities = buildUserAuthorities(appUser);
|
|
||||||
|
|
||||||
return org.springframework.security.core.userdetails.User.builder()
|
|
||||||
.username(appUser.getUsername())
|
|
||||||
.password(appUser.getPassword())
|
|
||||||
.authorities(authorities)
|
|
||||||
.accountExpired(false)
|
|
||||||
.accountLocked(isAccountLocked(appUser))
|
|
||||||
.credentialsExpired(isCredentialsExpired(appUser))
|
|
||||||
.disabled(!"1".equals(appUser.getStatus()))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建用户权限
|
|
||||||
*
|
|
||||||
* @param appUser 用户信息
|
|
||||||
* @return 权限集合
|
|
||||||
*/
|
|
||||||
private Collection<GrantedAuthority> buildUserAuthorities(User appUser) {
|
|
||||||
Set<GrantedAuthority> authorities = new HashSet<>();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 根据用户类型添加基本角色权限
|
|
||||||
if ("0".equals(appUser.getUsertype())) {
|
|
||||||
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
|
|
||||||
} else {
|
|
||||||
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询用户的角色
|
|
||||||
// QueryWrapper<RoleUser> roleUserQuery = new QueryWrapper<>();
|
|
||||||
// roleUserQuery.eq("userid", appUser.getId());
|
|
||||||
// List<RoleUser> roleUsers = appRoleUserService.list(roleUserQuery);
|
|
||||||
//
|
|
||||||
// if (!roleUsers.isEmpty()) {
|
|
||||||
// // 获取角色ID列表
|
|
||||||
// List<String> roleIds = roleUsers.stream()
|
|
||||||
// .map(AppRoleUser::getRoleid)
|
|
||||||
// .collect(Collectors.toList());
|
|
||||||
//
|
|
||||||
// // 查询角色信息并添加角色权限
|
|
||||||
// List<AppRole> roles = appRoleService.listByIds(roleIds);
|
|
||||||
// for (AppRole role : roles) {
|
|
||||||
// if ("1".equals(role.getIsvaild())) {
|
|
||||||
// // 添加角色权限,格式:ROLE_角色编码
|
|
||||||
// if (StringUtils.hasText(role.getRolecode())) {
|
|
||||||
// authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getRolecode().toUpperCase()));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // 查询角色关联的菜单权限
|
|
||||||
// QueryWrapper<AppRoleMenu> roleMenuQuery = new QueryWrapper<>();
|
|
||||||
// roleMenuQuery.in("roleid", roleIds);
|
|
||||||
// List<AppRoleMenu> roleMenus = appRoleMenuService.list(roleMenuQuery);
|
|
||||||
//
|
|
||||||
// if (!roleMenus.isEmpty()) {
|
|
||||||
// // 获取菜单ID列表
|
|
||||||
// List<String> menuIds = roleMenus.stream()
|
|
||||||
// .map(AppRoleMenu::getMenuid)
|
|
||||||
// .distinct()
|
|
||||||
// .collect(Collectors.toList());
|
|
||||||
//
|
|
||||||
// // 查询菜单信息并添加菜单权限
|
|
||||||
// List<AppMenu> menus = appMenuService.listByIds(menuIds);
|
|
||||||
// for (AppMenu menu : menus) {
|
|
||||||
// if ("1".equals(menu.getIsdisplay()) && StringUtils.hasText(menu.getCode())) {
|
|
||||||
// // 添加菜单权限,格式:菜单编码
|
|
||||||
// authorities.add(new SimpleGrantedAuthority(menu.getCode()));
|
|
||||||
//
|
|
||||||
// // 根据菜单类型添加操作权限
|
|
||||||
// String menuCode = menu.getCode();
|
|
||||||
// if (StringUtils.hasText(menuCode)) {
|
|
||||||
// // 为每个菜单添加基本操作权限
|
|
||||||
// authorities.add(new SimpleGrantedAuthority(menuCode + ":list"));
|
|
||||||
// authorities.add(new SimpleGrantedAuthority(menuCode + ":detail"));
|
|
||||||
//
|
|
||||||
// // 管理员拥有所有操作权限
|
|
||||||
// if ("0".equals(appUser.getUsertype())) {
|
|
||||||
// authorities.add(new SimpleGrantedAuthority(menuCode + ":add"));
|
|
||||||
// authorities.add(new SimpleGrantedAuthority(menuCode + ":edit"));
|
|
||||||
// authorities.add(new SimpleGrantedAuthority(menuCode + ":delete"));
|
|
||||||
// authorities.add(new SimpleGrantedAuthority(menuCode + ":permission"));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
log.debug("用户 {} 的权限列表: {}", appUser.getUsername(),
|
|
||||||
authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("构建用户权限失败: {}", e.getMessage(), e);
|
|
||||||
// 发生异常时,至少保证基本角色权限
|
|
||||||
authorities.clear();
|
|
||||||
if ("0".equals(appUser.getUsertype())) {
|
|
||||||
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
|
|
||||||
} else {
|
|
||||||
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return authorities;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查账户是否被锁定
|
|
||||||
*
|
|
||||||
* @param appUser 用户信息
|
|
||||||
* @return 是否被锁定
|
|
||||||
*/
|
|
||||||
private boolean isAccountLocked(User appUser) {
|
|
||||||
// 检查登录失败锁定时间
|
|
||||||
if (appUser.getFailedlocktime() != null) {
|
|
||||||
// 如果锁定时间还未过期,则账户被锁定
|
|
||||||
return appUser.getFailedlocktime().isAfter(java.time.LocalDateTime.now());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查凭证是否过期
|
|
||||||
*
|
|
||||||
* @param appUser 用户信息
|
|
||||||
* @return 是否过期
|
|
||||||
*/
|
|
||||||
private boolean isCredentialsExpired(User appUser) {
|
|
||||||
// 检查密码是否过期
|
|
||||||
if (appUser.getPwdresettime() != null && appUser.getPwdvalidperiod() != null) {
|
|
||||||
java.time.LocalDateTime expireTime = appUser.getPwdresettime().plusDays(appUser.getPwdvalidperiod());
|
|
||||||
return expireTime.isBefore(java.time.LocalDateTime.now());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
package com.stdproject.config;
|
package com.stdproject.config;
|
||||||
|
|
||||||
|
import com.stdproject.service.CustomUserDetailsService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@ -11,11 +12,9 @@ import org.springframework.security.config.annotation.method.configuration.Enabl
|
|||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter;
|
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.cors.CorsConfigurationSource;
|
import org.springframework.web.cors.CorsConfigurationSource;
|
||||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||||
|
@ -28,6 +28,10 @@ public class WebConfig implements WebMvcConfigurer {
|
|||||||
return CacheUtil.newTimedCache(jwtExpirationMs);
|
return CacheUtil.newTimedCache(jwtExpirationMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Cache<String, String> loginuserCache() {
|
||||||
|
return CacheUtil.newLRUCache(200);//用户登录缓存数 缺省200
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 静态资源处理
|
* 静态资源处理
|
||||||
*/
|
*/
|
||||||
|
@ -60,7 +60,7 @@ public class MenuController {
|
|||||||
return ResponseResult.error("没有菜单ID");
|
return ResponseResult.error("没有菜单ID");
|
||||||
}
|
}
|
||||||
//填写 当前用户名称
|
//填写 当前用户名称
|
||||||
menu.setLastmodifier(AuthUtils.getUser().getUserId().toString());
|
// menu.setLastmodifier(AuthUtils.getUser().getUserId().toString());
|
||||||
//填写 当前日期
|
//填写 当前日期
|
||||||
menu.setLastmodifydate(LocalDateTime.now());
|
menu.setLastmodifydate(LocalDateTime.now());
|
||||||
boolean isOk = menuService.updateById(menu);
|
boolean isOk = menuService.updateById(menu);
|
||||||
@ -82,8 +82,9 @@ public class MenuController {
|
|||||||
***********************************/
|
***********************************/
|
||||||
@PostMapping("/getMenuTree")
|
@PostMapping("/getMenuTree")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public List<Map<String, Object>> getMenuTree(String appId, String name, String isdisplay) {
|
public ResponseResult getMenuTree(String appId, String name, String isdisplay) {
|
||||||
return menuService.getMenuTree(appId, name, isdisplay);
|
List<Map<String, Object>> list= menuService.getMenuTree(appId, name, isdisplay);
|
||||||
|
return ResponseResult.successData(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -133,7 +134,7 @@ public class MenuController {
|
|||||||
//根据id 修改是否显示 ,最近修改人,最近修改时间
|
//根据id 修改是否显示 ,最近修改人,最近修改时间
|
||||||
updateWrapper.eq("id", id)
|
updateWrapper.eq("id", id)
|
||||||
.set("isdisplay", isdisplay)
|
.set("isdisplay", isdisplay)
|
||||||
.set("lastmodifier", AuthUtils.getUser().getUserId().toString())
|
// .set("lastmodifier", AuthUtils.getUser().getUserId().toString())
|
||||||
.set("lastmodifydate", new Timestamp(System.currentTimeMillis()));
|
.set("lastmodifydate", new Timestamp(System.currentTimeMillis()));
|
||||||
boolean ok = menuService.update(updateWrapper);
|
boolean ok = menuService.update(updateWrapper);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
@ -157,7 +158,7 @@ public class MenuController {
|
|||||||
//根据id 修改关联模块ID ,最近修改人,最近修改时间
|
//根据id 修改关联模块ID ,最近修改人,最近修改时间
|
||||||
updateWrapper.eq("id", id)
|
updateWrapper.eq("id", id)
|
||||||
.set("module_id", moduleId)
|
.set("module_id", moduleId)
|
||||||
.set("lastmodifier", AuthUtils.getUser().getUserId().toString())
|
// .set("lastmodifier", AuthUtils.getUser().getUserId().toString())
|
||||||
.set("lastmodifydate", new Timestamp(System.currentTimeMillis()));
|
.set("lastmodifydate", new Timestamp(System.currentTimeMillis()));
|
||||||
boolean ok = menuService.update(updateWrapper);
|
boolean ok = menuService.update(updateWrapper);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
@ -176,8 +177,8 @@ public class MenuController {
|
|||||||
***********************************/
|
***********************************/
|
||||||
@PostMapping("/permissionAssignment")
|
@PostMapping("/permissionAssignment")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public List<Map<String, Object>> permissionAssignment(String appId, String roleId) {
|
public ResponseResult permissionAssignment(String appId, String roleId) {
|
||||||
|
List<Map<String, Object>> list=menuService.permissionAssignment(appId,roleId);
|
||||||
return menuService.permissionAssignment(appId,roleId);
|
return ResponseResult.successData( list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
package com.stdproject.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.stdproject.config.ResponseResult;
|
||||||
|
import com.stdproject.entity.Module;
|
||||||
|
import com.stdproject.service.IModuleService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 应用_系统模块 前端控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author zhengsl
|
||||||
|
* @since 2025-03-25
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/module")
|
||||||
|
public class ModuleController {
|
||||||
|
// 添加Service注入
|
||||||
|
@Resource
|
||||||
|
private IModuleService moduleService;
|
||||||
|
|
||||||
|
// 分页查询模块列表
|
||||||
|
@GetMapping("/list")
|
||||||
|
public ResponseResult page(@RequestParam String appId) {
|
||||||
|
QueryWrapper<Module> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.eq("app_id",appId);
|
||||||
|
wrapper.orderByAsc("pid","sort"); // 按编码倒序排列
|
||||||
|
List<Map<String, Object>> list = moduleService.listMaps(wrapper);
|
||||||
|
return ResponseResult.successData(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除模块
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public ResponseResult remove(@PathVariable String id) {
|
||||||
|
return ResponseResult.successData(moduleService.removeById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取模块详情
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public ResponseResult getById(@PathVariable String id) {
|
||||||
|
Map<String, Object> moduleMap=null;
|
||||||
|
try {
|
||||||
|
LambdaQueryWrapper<Module> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(Module::getId, id);
|
||||||
|
moduleMap = moduleService.getMap(wrapper);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return ResponseResult.successData(moduleMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -69,7 +69,7 @@ public class OrganizationController {
|
|||||||
return ResponseResult.error("组织信息不能为空");
|
return ResponseResult.error("组织信息不能为空");
|
||||||
}
|
}
|
||||||
//填写 最近修改者
|
//填写 最近修改者
|
||||||
organization.setLastmodifier(AuthUtils.getUser().getUserId().toString());
|
// organization.setLastmodifier(AuthUtils.getUser().getUserId().toString());
|
||||||
//填写 最近修改时间
|
//填写 最近修改时间
|
||||||
organization.setLastmodifydate(LocalDateTime.now());
|
organization.setLastmodifydate(LocalDateTime.now());
|
||||||
//根据id 修改系统组织
|
//根据id 修改系统组织
|
||||||
@ -93,8 +93,9 @@ public class OrganizationController {
|
|||||||
***********************************/
|
***********************************/
|
||||||
@PostMapping("/getOrganizations")
|
@PostMapping("/getOrganizations")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public List<Map<String, Object>> getOrganizations(String appId, String orgtype, String parentid, String orgName) {
|
public ResponseResult getOrganizations(String appId, String orgtype, String parentid, String orgName) {
|
||||||
return organizationService.getOrganizations(appId,orgtype, parentid, orgName);
|
List<Map<String, Object>> list=organizationService.getOrganizations(appId,orgtype, parentid, orgName);
|
||||||
|
return ResponseResult.successData(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
@ -156,7 +157,7 @@ public class OrganizationController {
|
|||||||
UpdateWrapper<Organization> updateWrapper = new UpdateWrapper<>();
|
UpdateWrapper<Organization> updateWrapper = new UpdateWrapper<>();
|
||||||
updateWrapper.eq("id", id)
|
updateWrapper.eq("id", id)
|
||||||
.set("isvaild", isvaild)
|
.set("isvaild", isvaild)
|
||||||
.set("lastmodifier", AuthUtils.getUser().getUserId().toString())
|
// .set("lastmodifier", AuthUtils.getUser().getUserId().toString())
|
||||||
.set("lastmodifydate", LocalDateTime.now());
|
.set("lastmodifydate", LocalDateTime.now());
|
||||||
boolean isOk = organizationService.update(updateWrapper);
|
boolean isOk = organizationService.update(updateWrapper);
|
||||||
if (isOk) {
|
if (isOk) {
|
||||||
|
@ -63,7 +63,7 @@ public class RoleController {
|
|||||||
return ResponseResult.error("需要提交角色ID!");
|
return ResponseResult.error("需要提交角色ID!");
|
||||||
}
|
}
|
||||||
//更新最近修改人
|
//更新最近修改人
|
||||||
role.setLastmodifier(AuthUtils.getUser().getUserId().toString());
|
// role.setLastmodifier(AuthUtils.getUser().getUserId().toString());
|
||||||
//更新最近修改时间
|
//更新最近修改时间
|
||||||
role.setLastmodifydate(LocalDateTime.now());
|
role.setLastmodifydate(LocalDateTime.now());
|
||||||
//根据id更新角色信息
|
//根据id更新角色信息
|
||||||
@ -84,8 +84,9 @@ public class RoleController {
|
|||||||
***********************************/
|
***********************************/
|
||||||
@PostMapping("/listRole")
|
@PostMapping("/listRole")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public List<Role> listRole(String appId, String rolename) {
|
public ResponseResult listRole(String appId, String rolename) {
|
||||||
return roleService.listRole(appId,rolename);
|
List<Role> list=roleService.listRole(appId,rolename);
|
||||||
|
return ResponseResult.successData( list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
@ -152,7 +153,7 @@ public class RoleController {
|
|||||||
//根据id 更新业务范围,最近修改人,最近修改时间
|
//根据id 更新业务范围,最近修改人,最近修改时间
|
||||||
updateWrapper.eq("id", id)
|
updateWrapper.eq("id", id)
|
||||||
.set("isvaild", isvaild)
|
.set("isvaild", isvaild)
|
||||||
.set("lastmodifier", AuthUtils.getUser().getUserId().toString())
|
// .set("lastmodifier", AuthUtils.getUser().getUserId().toString())
|
||||||
.set("lastmodifydate",LocalDateTime.now());
|
.set("lastmodifydate",LocalDateTime.now());
|
||||||
boolean ok = roleService.update(updateWrapper);
|
boolean ok = roleService.update(updateWrapper);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
|
@ -1,16 +1,42 @@
|
|||||||
package com.stdproject.controller;
|
package com.stdproject.controller;
|
||||||
|
|
||||||
import cn.hutool.core.util.ObjUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import cn.hutool.jwt.JWTUtil;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.stdproject.config.ResponseResult;
|
import com.stdproject.config.ResponseResult;
|
||||||
|
import com.stdproject.config.WebConfig;
|
||||||
|
import com.stdproject.entity.AppOptLog;
|
||||||
|
import com.stdproject.entity.LoginUser;
|
||||||
import com.stdproject.entity.User;
|
import com.stdproject.entity.User;
|
||||||
|
import com.stdproject.service.IAppOptLogService;
|
||||||
import com.stdproject.service.IUserService;
|
import com.stdproject.service.IUserService;
|
||||||
|
import com.stdproject.utils.JwtUtils;
|
||||||
|
import com.stdproject.utils.RsaUtils;
|
||||||
|
import com.stdproject.utils.commonUtils;
|
||||||
import io.micrometer.common.util.StringUtils;
|
import io.micrometer.common.util.StringUtils;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
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.DisabledException;
|
||||||
|
import org.springframework.security.authentication.LockedException;
|
||||||
|
import org.springframework.security.authentication.AccountExpiredException;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
@ -28,6 +54,18 @@ public class UserController {
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private IUserService userService;
|
private IUserService userService;
|
||||||
|
@Value("${spring.security.rsa.private-key}")
|
||||||
|
private String privateKey;
|
||||||
|
@Value("${spring.security.jwt.expiration-ms}")
|
||||||
|
private Long jwtExpirationMs;
|
||||||
|
@Autowired
|
||||||
|
private AuthenticationManager authenticationManager;
|
||||||
|
@Autowired
|
||||||
|
private WebConfig webConfig;
|
||||||
|
@Resource
|
||||||
|
private IAppOptLogService sysLogService;
|
||||||
|
@Autowired
|
||||||
|
private JwtUtils jwtUtils;
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
* 用途说明:新增系统用户
|
* 用途说明:新增系统用户
|
||||||
@ -115,7 +153,6 @@ public class UserController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
* 用途说明:设置账号状态(管理员)
|
* 用途说明:设置账号状态(管理员)
|
||||||
* 参数说明
|
* 参数说明
|
||||||
@ -159,22 +196,91 @@ public class UserController {
|
|||||||
return ResponseResult.error();
|
return ResponseResult.error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public ResponseResult login(String appid,String username, String password) {
|
public ResponseResult login(String username, String password) throws Exception {
|
||||||
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
|
try {
|
||||||
return ResponseResult.error("用户名称或者密码不能为空!");
|
// 密码解密
|
||||||
|
String encrypt_password = RsaUtils.decryptByPrivateKey(privateKey, password);
|
||||||
|
//如果认证通过了,使用userId生成token token存入ResponseResult返回
|
||||||
|
UsernamePasswordAuthenticationToken authenticationToken =
|
||||||
|
new UsernamePasswordAuthenticationToken(username,
|
||||||
|
encrypt_password);
|
||||||
|
Authentication authenticate =
|
||||||
|
authenticationManager.authenticate(authenticationToken);
|
||||||
|
LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
|
||||||
|
// 获取请求信息
|
||||||
|
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||||
|
HttpServletRequest request = attributes.getRequest();
|
||||||
|
AppOptLog sysLog = new AppOptLog();
|
||||||
|
sysLog.setUsercode(username);
|
||||||
|
sysLog.setUsername(loginUser.getUser().getNickname());
|
||||||
|
sysLog.setRequestip(commonUtils.getIpAddress(request));
|
||||||
|
sysLog.setBrowser(commonUtils.getBrowser(request));
|
||||||
|
sysLog.setOpttype("登录(login)");
|
||||||
|
sysLog.setModule("用户登录");
|
||||||
|
String className = this.getClass().getName();
|
||||||
|
String method =
|
||||||
|
Thread.currentThread().getStackTrace()[1].getMethodName();
|
||||||
|
sysLog.setMethod(className + "." + method + "()");
|
||||||
|
//sysLog.setParams(user.toString());
|
||||||
|
sysLog.setDescription(loginUser.getUser().getNickname() + "登录系统!");
|
||||||
|
sysLog.setLogtime(LocalDateTime.now());
|
||||||
|
sysLogService.save(sysLog);
|
||||||
|
String userId = loginUser.getUser().getId();
|
||||||
|
long expireTime = System.currentTimeMillis() + jwtExpirationMs;
|
||||||
|
Map<String, Object> map = new HashMap();
|
||||||
|
map.put("userid", userId);
|
||||||
|
map.put("username", loginUser.getUsername());
|
||||||
|
map.put("expire_time", expireTime);
|
||||||
|
String token = jwtUtils.generateToken(loginUser.getUsername(), userId);
|
||||||
|
map.put("token", token);
|
||||||
|
//把完整的用户信息存入到HuTool缓存中,userId作为key
|
||||||
|
String jsonStr = JSONUtil.toJsonStr(loginUser);
|
||||||
|
webConfig.loginuserCache().put("login:" + userId, jsonStr);
|
||||||
|
return ResponseResult.successData(map);
|
||||||
}
|
}
|
||||||
// 根据用户名查询用户
|
catch (BadCredentialsException e) {
|
||||||
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
|
// 账号密码验证错误
|
||||||
User user = userService.getOne(queryWrapper.eq("app_id",appid).eq("username", username));
|
return ResponseResult.error("账号或密码错误,请检查!");
|
||||||
if (ObjUtil.isEmpty( user)) {
|
} catch (DisabledException e) {
|
||||||
return ResponseResult.error(String.format("%s您输入的用户账号不存在!", username));
|
// 账号已停用
|
||||||
}
|
return ResponseResult.error("账号已停用,不能登录!");
|
||||||
if(password.equals(user.getPassword())){
|
} catch (LockedException e) {
|
||||||
return ResponseResult.successData(user);
|
// 账号被锁定
|
||||||
}else{
|
return ResponseResult.error("账号被锁定,不能登录!");
|
||||||
return ResponseResult.error("您输入的密码错误!");
|
} catch (AccountExpiredException e) {
|
||||||
|
// 账号已过期
|
||||||
|
return ResponseResult.error("账号密码已过有效期,不能登录!");
|
||||||
|
} catch (AuthenticationException e) {
|
||||||
|
// 捕获其他认证异常
|
||||||
|
return ResponseResult.error("认证失败:" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@PostMapping("/logout")
|
||||||
|
@ResponseBody
|
||||||
|
public ResponseResult logout() {
|
||||||
|
//获取SecurityContextHolder中的用户id
|
||||||
|
UsernamePasswordAuthenticationToken authentication =
|
||||||
|
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
LoginUser loginuser = (LoginUser) authentication.getPrincipal();
|
||||||
|
String userId = loginuser.getUser().getId();
|
||||||
|
//删除redis中的登陆用户信息
|
||||||
|
webConfig.loginuserCache().remove("login:" + userId);
|
||||||
|
//记录退出日志
|
||||||
|
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||||
|
HttpServletRequest request = attributes.getRequest();
|
||||||
|
AppOptLog sysLog = new AppOptLog();
|
||||||
|
sysLog.setUsercode(loginuser.getUsername());
|
||||||
|
sysLog.setUsername(loginuser.getUser().getNickname());
|
||||||
|
sysLog.setRequestip(commonUtils.getIpAddress(request));
|
||||||
|
sysLog.setBrowser(commonUtils.getBrowser(request));
|
||||||
|
sysLog.setOpttype("其他(other)");
|
||||||
|
sysLog.setModule("注销退出");
|
||||||
|
sysLog.setDescription("注销退出系统!");
|
||||||
|
sysLog.setLogtime(LocalDateTime.now());
|
||||||
|
sysLogService.save(sysLog);
|
||||||
|
return ResponseResult.success();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
109
backend/src/main/java/com/stdproject/entity/Application.java
Normal file
109
backend/src/main/java/com/stdproject/entity/Application.java
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
package com.stdproject.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 应用系统
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author zhengsl
|
||||||
|
* @since 2025-03-24
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@TableName("app_application")
|
||||||
|
public class Application implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID
|
||||||
|
*/
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用类型 01-数据展示分析
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用编号 自动生成:000001
|
||||||
|
*/
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用简称
|
||||||
|
*/
|
||||||
|
private String simplename;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建日期
|
||||||
|
*/
|
||||||
|
private LocalDateTime createdate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用描述
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用图片 base64存储
|
||||||
|
*/
|
||||||
|
private String image;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用配置 JSON格式存储其他配置相关信息
|
||||||
|
*/
|
||||||
|
private String appconfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库配置 JSON格式存储数据库信息配置(数据库用于存储此应用系统的所有配置数据)
|
||||||
|
*/
|
||||||
|
private String dbconfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户单位 使用这个应用系统的组织单位
|
||||||
|
*/
|
||||||
|
private String organization;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态 01-初始创建 02-正常运行 09-已停用
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近修改者
|
||||||
|
*/
|
||||||
|
private String lastmodifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近修改日期
|
||||||
|
*/
|
||||||
|
private LocalDateTime lastmodifydate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备用1
|
||||||
|
*/
|
||||||
|
private String custom1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备用2
|
||||||
|
*/
|
||||||
|
private String custom2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备用3
|
||||||
|
*/
|
||||||
|
private String custom3;
|
||||||
|
}
|
178
backend/src/main/java/com/stdproject/entity/Module.java
Normal file
178
backend/src/main/java/com/stdproject/entity/Module.java
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
package com.stdproject.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.apache.ibatis.type.JdbcType;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 应用_系统模块
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author zhengsl
|
||||||
|
* @since 2025-03-25
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@TableName("app_module")
|
||||||
|
public class Module implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键
|
||||||
|
*/
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用ID 关联应用系统
|
||||||
|
*/
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 父级ID 父级模块
|
||||||
|
*/
|
||||||
|
@TableField(value = "pid", jdbcType = JdbcType.VARCHAR)
|
||||||
|
private String pid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 层级
|
||||||
|
*/
|
||||||
|
private Integer level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点类型 01-目录 02-模块
|
||||||
|
*/
|
||||||
|
private String nodeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型 01-数据大屏 02-数据看板 03-弹窗页面 04-填报页面 06-移动端界面 09-自定义页面
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 样式数据
|
||||||
|
*/
|
||||||
|
@TableField(value = "canvas_style_data", jdbcType = JdbcType.VARCHAR)
|
||||||
|
private String canvasStyleData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件数据
|
||||||
|
*/
|
||||||
|
@TableField(value = "component_data", jdbcType = JdbcType.VARCHAR)
|
||||||
|
private String componentData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态 0-未发布 1-已发布
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否单独打开水印 0-关闭 1-开启
|
||||||
|
*/
|
||||||
|
private Integer selfWatermarkStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序 目录内的排序号
|
||||||
|
*/
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建人
|
||||||
|
*/
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新人
|
||||||
|
*/
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据来源
|
||||||
|
*/
|
||||||
|
private String source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标志
|
||||||
|
*/
|
||||||
|
private Byte deleteFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime deleteTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除人
|
||||||
|
*/
|
||||||
|
private String deleteBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可视化资源版本
|
||||||
|
*/
|
||||||
|
private Integer version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容标识
|
||||||
|
*/
|
||||||
|
private String contentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容检查标识
|
||||||
|
*/
|
||||||
|
private String checkVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备用1
|
||||||
|
*/
|
||||||
|
private String custom1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备用2
|
||||||
|
*/
|
||||||
|
private String custom2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备用3
|
||||||
|
*/
|
||||||
|
private String custom3;
|
||||||
|
|
||||||
|
public Module(String appId, String name, String pid, Integer level, String nodeType, String type, Integer status, Integer sort, LocalDateTime createTime, String createBy){
|
||||||
|
|
||||||
|
this.appId = appId;
|
||||||
|
this.name = name;
|
||||||
|
this.pid = pid;
|
||||||
|
this.level = level;
|
||||||
|
this.nodeType = nodeType;
|
||||||
|
this.type = type;
|
||||||
|
this.status = status;
|
||||||
|
this.sort = sort;
|
||||||
|
this.createTime = createTime;
|
||||||
|
this.createBy = createBy;
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.stdproject.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
|
||||||
|
import com.stdproject.entity.Application;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 应用系统 Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author zhengsl
|
||||||
|
* @since 2025-03-24
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ApplicationMapper extends BaseMapper<Application> {
|
||||||
|
@Select("SELECT MAX(CAST(code AS UNSIGNED)) FROM app_application")
|
||||||
|
Integer getMaxCode();
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.stdproject.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import com.stdproject.entity.Module;
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 应用_系统模块 Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author zhengsl
|
||||||
|
* @since 2025-03-25
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ModuleMapper extends BaseMapper<Module> {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,147 @@
|
|||||||
|
package com.stdproject.service;
|
||||||
|
|
||||||
|
import com.stdproject.entity.LoginUser;
|
||||||
|
import com.stdproject.entity.Menu;
|
||||||
|
import com.stdproject.entity.Role;
|
||||||
|
import com.stdproject.entity.User;
|
||||||
|
import com.stdproject.mapper.MenuMapper;
|
||||||
|
import com.stdproject.mapper.RoleMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义用户详情服务
|
||||||
|
* 实现Spring Security的UserDetailsService接口
|
||||||
|
*
|
||||||
|
* @author StdProject
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class CustomUserDetailsService implements UserDetailsService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IUserService appUserService;
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IMenuService appMenuService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RoleMapper roleMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MenuMapper menuMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserDetails loadUserByUsername(String username) {
|
||||||
|
User appUser = appUserService.findByUsername(username);
|
||||||
|
if (appUser == null) {
|
||||||
|
throw new UsernameNotFoundException("用户不存在: " + username);
|
||||||
|
}
|
||||||
|
Collection<GrantedAuthority> authorities = buildUserAuthorities(appUser);
|
||||||
|
LoginUser loginUser = new LoginUser(appUser,authorities);
|
||||||
|
return loginUser;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建用户权限
|
||||||
|
*
|
||||||
|
* @param appUser 用户信息
|
||||||
|
* @return 权限集合
|
||||||
|
*/
|
||||||
|
private Collection<GrantedAuthority> buildUserAuthorities(User appUser) {
|
||||||
|
Set<GrantedAuthority> authorities = new HashSet<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 根据用户类型添加基本角色权限
|
||||||
|
if ("0".equals(appUser.getUsertype())) {
|
||||||
|
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
|
||||||
|
} else {
|
||||||
|
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用RoleMapper直接查询用户的角色信息
|
||||||
|
List<Role> roles = roleMapper.getRoleByUserId(appUser.getId());
|
||||||
|
|
||||||
|
if (!roles.isEmpty()) {
|
||||||
|
// 处理角色权限
|
||||||
|
for (Role role : roles) {
|
||||||
|
if ("1".equals(role.getIsvaild())) {
|
||||||
|
// 添加角色权限,格式:ROLE_角色编码
|
||||||
|
if (StringUtils.hasText(role.getRolecode())) {
|
||||||
|
authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getRolecode().toUpperCase()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 获取角色ID列表
|
||||||
|
List<String> roleIds = roles.stream()
|
||||||
|
.map(Role::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 处理每个角色的菜单权限
|
||||||
|
for (String roleId : roleIds) {
|
||||||
|
// 使用MenuMapper直接查询角色关联的菜单ID
|
||||||
|
List<String> menuIds = menuMapper.selectMenuByRoleId(appUser.getAppId(), roleId);
|
||||||
|
|
||||||
|
if (!menuIds.isEmpty()) {
|
||||||
|
// 查询菜单信息并添加菜单权限
|
||||||
|
List<Menu> menus = appMenuService.listByIds(menuIds);
|
||||||
|
for (Menu menu : menus) {
|
||||||
|
if ("1".equals(menu.getIsdisplay()) && StringUtils.hasText(menu.getCode())) {
|
||||||
|
// 添加菜单权限,格式:菜单编码
|
||||||
|
authorities.add(new SimpleGrantedAuthority(menu.getCode()));
|
||||||
|
|
||||||
|
// 根据菜单类型添加操作权限
|
||||||
|
String menuCode = menu.getCode();
|
||||||
|
if (StringUtils.hasText(menuCode)) {
|
||||||
|
// 为每个菜单添加基本操作权限
|
||||||
|
authorities.add(new SimpleGrantedAuthority(menuCode + ":list"));
|
||||||
|
authorities.add(new SimpleGrantedAuthority(menuCode + ":detail"));
|
||||||
|
|
||||||
|
// 管理员拥有所有操作权限
|
||||||
|
if ("0".equals(appUser.getUsertype())) {
|
||||||
|
authorities.add(new SimpleGrantedAuthority(menuCode + ":add"));
|
||||||
|
authorities.add(new SimpleGrantedAuthority(menuCode + ":edit"));
|
||||||
|
authorities.add(new SimpleGrantedAuthority(menuCode + ":delete"));
|
||||||
|
authorities.add(new SimpleGrantedAuthority(menuCode + ":permission"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("用户 {} 的权限列表: {}", appUser.getUsername(),
|
||||||
|
authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("构建用户权限失败: {}", e.getMessage(), e);
|
||||||
|
// 发生异常时,至少保证基本角色权限
|
||||||
|
authorities.clear();
|
||||||
|
if ("0".equals(appUser.getUsertype())) {
|
||||||
|
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
|
||||||
|
} else {
|
||||||
|
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return authorities;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.stdproject.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.stdproject.entity.Application;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 应用系统 服务类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author zhengsl
|
||||||
|
* @since 2025-03-24
|
||||||
|
*/
|
||||||
|
public interface IApplicationService extends IService<Application> {
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.stdproject.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.stdproject.entity.Module;
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 应用_系统模块 服务类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author zhengsl
|
||||||
|
* @since 2025-03-25
|
||||||
|
*/
|
||||||
|
public interface IModuleService extends IService<Module> {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.stdproject.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.stdproject.entity.Application;
|
||||||
|
import com.stdproject.mapper.ApplicationMapper;
|
||||||
|
import com.stdproject.service.IApplicationService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 应用系统 服务实现类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author zhengsl
|
||||||
|
* @since 2025-03-24
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class ApplicationServiceImpl extends ServiceImpl<ApplicationMapper, Application> implements IApplicationService {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.stdproject.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.stdproject.entity.Module;
|
||||||
|
import com.stdproject.mapper.ModuleMapper;
|
||||||
|
import com.stdproject.service.IModuleService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 应用_系统模块 服务实现类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author zhengsl
|
||||||
|
* @since 2025-03-25
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class ModuleServiceImpl extends ServiceImpl<ModuleMapper, Module> implements IModuleService {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -166,7 +166,7 @@ public class OrganizationServiceImpl extends ServiceImpl<OrganizationMapper, Org
|
|||||||
//填写 编号
|
//填写 编号
|
||||||
organization.setOrgcode(code);
|
organization.setOrgcode(code);
|
||||||
//填写 当前用户名称
|
//填写 当前用户名称
|
||||||
organization.setLastmodifier(AuthUtils.getUser().getUserId().toString());
|
// organization.setLastmodifier(AuthUtils.getUser().getUserId().toString());
|
||||||
//填写 当前日期
|
//填写 当前日期
|
||||||
organization.setLastmodifydate(LocalDateTime.now());
|
organization.setLastmodifydate(LocalDateTime.now());
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IR
|
|||||||
role.setIsvaild("1");
|
role.setIsvaild("1");
|
||||||
}
|
}
|
||||||
//添加最近修改者
|
//添加最近修改者
|
||||||
role.setLastmodifier(AuthUtils.getUser().getUserId().toString());
|
// role.setLastmodifier(AuthUtils.getUser().getUserId().toString());
|
||||||
//添加最近修改时间
|
//添加最近修改时间
|
||||||
role.setLastmodifydate(LocalDateTime.now());
|
role.setLastmodifydate(LocalDateTime.now());
|
||||||
return this.save(role);
|
return this.save(role);
|
||||||
|
@ -12,6 +12,7 @@ import com.stdproject.entity.User; // 确保 User 类存在并路径正确
|
|||||||
import com.stdproject.mapper.RoleMapper;
|
import com.stdproject.mapper.RoleMapper;
|
||||||
import com.stdproject.mapper.UserMapper;
|
import com.stdproject.mapper.UserMapper;
|
||||||
import com.stdproject.service.IUserService; // 确保接口存在
|
import com.stdproject.service.IUserService; // 确保接口存在
|
||||||
|
import com.stdproject.utils.EncryptUtils;
|
||||||
import io.gisbi.utils.AuthUtils;
|
import io.gisbi.utils.AuthUtils;
|
||||||
import io.gisbi.utils.RsaUtils;
|
import io.gisbi.utils.RsaUtils;
|
||||||
import io.micrometer.common.util.StringUtils;
|
import io.micrometer.common.util.StringUtils;
|
||||||
@ -64,12 +65,12 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
|
|||||||
Map<String, String> result = new HashMap<>();
|
Map<String, String> result = new HashMap<>();
|
||||||
//普通用户
|
//普通用户
|
||||||
//设置缺省密码
|
//设置缺省密码
|
||||||
String cryptPassword = RsaUtils.encryptStr(PASSWORD_VALID);
|
String cryptPassword = EncryptUtils.md5(PASSWORD_VALID);;
|
||||||
user.setPassword(cryptPassword);
|
user.setPassword(cryptPassword);
|
||||||
//最近修改日期
|
//最近修改日期
|
||||||
user.setLastmodifydate(LocalDateTime.now());
|
user.setLastmodifydate(LocalDateTime.now());
|
||||||
//最近修改者
|
//最近修改者
|
||||||
user.setLastmodifier(AuthUtils.getUser().getUserId().toString());
|
// user.setLastmodifier(AuthUtils.getUser().getUserId().toString());
|
||||||
//账号有效 状态 1-有效 0-停用
|
//账号有效 状态 1-有效 0-停用
|
||||||
user.setStatus(DEFAULT_IS_VALID);
|
user.setStatus(DEFAULT_IS_VALID);
|
||||||
//判断注册的登录账号是否存在
|
//判断注册的登录账号是否存在
|
||||||
@ -274,8 +275,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
|
|||||||
String cryptPassword = PASSWORD_VALID;
|
String cryptPassword = PASSWORD_VALID;
|
||||||
updateWrapper.eq("id", id).set("password", cryptPassword)
|
updateWrapper.eq("id", id).set("password", cryptPassword)
|
||||||
.set("pwdresettime", LocalDateTime.now())
|
.set("pwdresettime", LocalDateTime.now())
|
||||||
.set("lastmodifydate", LocalDateTime.now())
|
.set("lastmodifydate", LocalDateTime.now());
|
||||||
.set("lastmodifier", AuthUtils.getUser().getUserId().toString());
|
// .set("lastmodifier", AuthUtils.getUser().getUserId().toString());
|
||||||
//是否修改成功
|
//是否修改成功
|
||||||
isOk = this.update(updateWrapper);
|
isOk = this.update(updateWrapper);
|
||||||
return isOk;
|
return isOk;
|
||||||
@ -295,8 +296,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IU
|
|||||||
//根据id修改用户状态,最近修改人,最近修改时间
|
//根据id修改用户状态,最近修改人,最近修改时间
|
||||||
updateWrapper.eq("id", id)
|
updateWrapper.eq("id", id)
|
||||||
.set("status", status)
|
.set("status", status)
|
||||||
.set("lastmodifydate", LocalDateTime.now())
|
.set("lastmodifydate", LocalDateTime.now());
|
||||||
.set("lastmodifier", AuthUtils.getUser().getUserId().toString());
|
// .set("lastmodifier", AuthUtils.getUser().getUserId().toString());
|
||||||
//是否修改成功
|
//是否修改成功
|
||||||
isOk = this.update(updateWrapper);
|
isOk = this.update(updateWrapper);
|
||||||
return isOk;
|
return isOk;
|
||||||
|
183
backend/src/main/java/com/stdproject/utils/RsaUtils.java
Normal file
183
backend/src/main/java/com/stdproject/utils/RsaUtils.java
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
package com.stdproject.utils;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
|
import java.security.interfaces.RSAPublicKey;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author https://www.cnblogs.com/nihaorz/p/10690643.html
|
||||||
|
* @description Rsa 工具类,公钥私钥生成,加解密
|
||||||
|
* @date 2020-05-18
|
||||||
|
**/
|
||||||
|
public class RsaUtils {
|
||||||
|
|
||||||
|
private static final String SRC = "123456";
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
System.out.println("\n");
|
||||||
|
RsaKeyPair keyPair = generateKeyPair();
|
||||||
|
System.out.println("公钥:" + keyPair.getPublicKey());
|
||||||
|
System.out.println("私钥:" + keyPair.getPrivateKey());
|
||||||
|
System.out.println("\n");
|
||||||
|
test1(keyPair);
|
||||||
|
System.out.println("\n");
|
||||||
|
test2(keyPair);
|
||||||
|
System.out.println("\n");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公钥加密私钥解密
|
||||||
|
*/
|
||||||
|
private static void test1(RsaKeyPair keyPair) throws Exception {
|
||||||
|
System.out.println("***************** 公钥加密私钥解密开始 *****************");
|
||||||
|
String text1 = encryptByPublicKey(keyPair.getPublicKey(), RsaUtils.SRC);
|
||||||
|
String text2 = decryptByPrivateKey(keyPair.getPrivateKey(), text1);
|
||||||
|
System.out.println("加密前:" + RsaUtils.SRC);
|
||||||
|
System.out.println("加密后:" + text1);
|
||||||
|
System.out.println("解密后:" + text2);
|
||||||
|
if (RsaUtils.SRC.equals(text2)) {
|
||||||
|
System.out.println("解密字符串和原始字符串一致,解密成功");
|
||||||
|
} else {
|
||||||
|
System.out.println("解密字符串和原始字符串不一致,解密失败");
|
||||||
|
}
|
||||||
|
System.out.println("***************** 公钥加密私钥解密结束 *****************");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私钥加密公钥解密
|
||||||
|
* @throws Exception /
|
||||||
|
*/
|
||||||
|
private static void test2(RsaKeyPair keyPair) throws Exception {
|
||||||
|
System.out.println("***************** 私钥加密公钥解密开始 *****************");
|
||||||
|
String text1 = encryptByPrivateKey(keyPair.getPrivateKey(), RsaUtils.SRC);
|
||||||
|
String text2 = decryptByPublicKey(keyPair.getPublicKey(), text1);
|
||||||
|
System.out.println("加密前:" + RsaUtils.SRC);
|
||||||
|
System.out.println("加密后:" + text1);
|
||||||
|
System.out.println("解密后:" + text2);
|
||||||
|
if (RsaUtils.SRC.equals(text2)) {
|
||||||
|
System.out.println("解密字符串和原始字符串一致,解密成功");
|
||||||
|
} else {
|
||||||
|
System.out.println("解密字符串和原始字符串不一致,解密失败");
|
||||||
|
}
|
||||||
|
System.out.println("***************** 私钥加密公钥解密结束 *****************");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公钥解密
|
||||||
|
*
|
||||||
|
* @param publicKeyText 公钥
|
||||||
|
* @param text 待解密的信息
|
||||||
|
* @return /
|
||||||
|
* @throws Exception /
|
||||||
|
*/
|
||||||
|
public static String decryptByPublicKey(String publicKeyText, String text) throws Exception {
|
||||||
|
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, publicKey);
|
||||||
|
byte[] result = cipher.doFinal(Base64.decodeBase64(text));
|
||||||
|
return new String(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私钥加密
|
||||||
|
*
|
||||||
|
* @param privateKeyText 私钥
|
||||||
|
* @param text 待加密的信息
|
||||||
|
* @return /
|
||||||
|
* @throws Exception /
|
||||||
|
*/
|
||||||
|
public static String encryptByPrivateKey(String privateKeyText, String text) throws Exception {
|
||||||
|
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA");
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
|
||||||
|
byte[] result = cipher.doFinal(text.getBytes());
|
||||||
|
return Base64.encodeBase64String(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私钥解密
|
||||||
|
*
|
||||||
|
* @param privateKeyText 私钥
|
||||||
|
* @param text 待解密的文本
|
||||||
|
* @return /
|
||||||
|
* @throws Exception /
|
||||||
|
*/
|
||||||
|
public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception {
|
||||||
|
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||||
|
byte[] result = cipher.doFinal(Base64.decodeBase64(text));
|
||||||
|
return new String(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公钥加密
|
||||||
|
*
|
||||||
|
* @param publicKeyText 公钥
|
||||||
|
* @param text 待加密的文本
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static String encryptByPublicKey(String publicKeyText, String text) throws Exception {
|
||||||
|
X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA");
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||||
|
byte[] result = cipher.doFinal(text.getBytes());
|
||||||
|
return Base64.encodeBase64String(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建RSA密钥对
|
||||||
|
*
|
||||||
|
* @return /
|
||||||
|
* @throws NoSuchAlgorithmException /
|
||||||
|
*/
|
||||||
|
public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {
|
||||||
|
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||||
|
keyPairGenerator.initialize(1024);
|
||||||
|
KeyPair keyPair = keyPairGenerator.generateKeyPair();
|
||||||
|
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
|
||||||
|
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
|
||||||
|
String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
|
||||||
|
String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
|
||||||
|
return new RsaKeyPair(publicKeyString, privateKeyString);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSA密钥对对象
|
||||||
|
*/
|
||||||
|
public static class RsaKeyPair {
|
||||||
|
|
||||||
|
private final String publicKey;
|
||||||
|
private final String privateKey;
|
||||||
|
|
||||||
|
public RsaKeyPair(String publicKey, String privateKey) {
|
||||||
|
this.publicKey = publicKey;
|
||||||
|
this.privateKey = privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPublicKey() {
|
||||||
|
return publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrivateKey() {
|
||||||
|
return privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
38
backend/src/main/java/com/stdproject/utils/commonUtils.java
Normal file
38
backend/src/main/java/com/stdproject/utils/commonUtils.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package com.stdproject.utils;
|
||||||
|
|
||||||
|
import cn.hutool.http.useragent.Browser;
|
||||||
|
import cn.hutool.http.useragent.UserAgent;
|
||||||
|
import cn.hutool.http.useragent.UserAgentUtil;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
public class commonUtils {
|
||||||
|
|
||||||
|
public static String getBrowser(HttpServletRequest request) {
|
||||||
|
UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
|
||||||
|
Browser browser = userAgent.getBrowser();
|
||||||
|
return browser.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取客户端IP地址
|
||||||
|
*/
|
||||||
|
public static String getIpAddress(HttpServletRequest request) {
|
||||||
|
String ip = request.getHeader("X-Forwarded-For");
|
||||||
|
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getHeader("Proxy-Client-IP");
|
||||||
|
}
|
||||||
|
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||||
|
}
|
||||||
|
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getHeader("HTTP_CLIENT_IP");
|
||||||
|
}
|
||||||
|
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
|
||||||
|
}
|
||||||
|
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getRemoteAddr();
|
||||||
|
}
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
}
|
@ -13,3 +13,6 @@ SPRING_PROFILES_ACTIVE=dev
|
|||||||
|
|
||||||
# CORS配置
|
# CORS配置
|
||||||
CORS_ALLOWED_ORIGINS=https://your-frontend.com
|
CORS_ALLOWED_ORIGINS=https://your-frontend.com
|
||||||
|
|
||||||
|
# RSA密钥
|
||||||
|
RSA_PRIVATE_KEY = MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
|
@ -46,6 +46,8 @@ spring:
|
|||||||
secret: ${JWT_SECRET:YourJWTSecretKeyForStdProjectBackendApplicationWhichIsVeryLongAndSecure2024!@#$%^&*()}
|
secret: ${JWT_SECRET:YourJWTSecretKeyForStdProjectBackendApplicationWhichIsVeryLongAndSecure2024!@#$%^&*()}
|
||||||
expiration-ms: ${JWT_EXPIRATION:86400000} # Token 过期时间 (例如: 24小时)
|
expiration-ms: ${JWT_EXPIRATION:86400000} # Token 过期时间 (例如: 24小时)
|
||||||
refresh-expiration-ms: ${JWT_REFRESH_EXPIRATION:604800000} # 刷新Token过期时间 (例如: 7天)
|
refresh-expiration-ms: ${JWT_REFRESH_EXPIRATION:604800000} # 刷新Token过期时间 (例如: 7天)
|
||||||
|
rsa:
|
||||||
|
private-key: ${RSA_PRIVATE_KEY:MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==}
|
||||||
|
|
||||||
mybatis-plus:
|
mybatis-plus:
|
||||||
mapper-locations: classpath*:/mapper/**/*.xml # MyBatis Mapper XML文件位置
|
mapper-locations: classpath*:/mapper/**/*.xml # MyBatis Mapper XML文件位置
|
||||||
|
44
frontend/components.d.ts
vendored
44
frontend/components.d.ts
vendored
@ -9,55 +9,11 @@ export {}
|
|||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
declare module '@vue/runtime-core' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
ElBreadcrumb: typeof import('element-plus-secondary/es')['ElBreadcrumb']
|
|
||||||
ElBreadcrumbItem: typeof import('element-plus-secondary/es')['ElBreadcrumbItem']
|
|
||||||
ElButton: typeof import('element-plus-secondary/es')['ElButton']
|
|
||||||
ElCard: typeof import('element-plus-secondary/es')['ElCard']
|
ElCard: typeof import('element-plus-secondary/es')['ElCard']
|
||||||
ElCheckbox: typeof import('element-plus-secondary/es')['ElCheckbox']
|
|
||||||
ElCheckboxGroup: typeof import('element-plus-secondary/es')['ElCheckboxGroup']
|
|
||||||
ElCol: typeof import('element-plus-secondary/es')['ElCol']
|
|
||||||
ElCollapse: typeof import('element-plus-secondary/es')['ElCollapse']
|
|
||||||
ElCollapseItem: typeof import('element-plus-secondary/es')['ElCollapseItem']
|
|
||||||
ElColorPicker: typeof import('element-plus-secondary/es')['ElColorPicker']
|
|
||||||
ElContainer: typeof import('element-plus-secondary/es')['ElContainer']
|
|
||||||
ElDatePicker: typeof import('element-plus-secondary/es')['ElDatePicker']
|
|
||||||
ElDialog: typeof import('element-plus-secondary/es')['ElDialog']
|
|
||||||
ElDivider: typeof import('element-plus-secondary/es')['ElDivider']
|
|
||||||
ElDropdown: typeof import('element-plus-secondary/es')['ElDropdown']
|
|
||||||
ElDropdownItem: typeof import('element-plus-secondary/es')['ElDropdownItem']
|
|
||||||
ElDropdownMenu: typeof import('element-plus-secondary/es')['ElDropdownMenu']
|
|
||||||
ElEmpty: typeof import('element-plus-secondary/es')['ElEmpty']
|
|
||||||
ElForm: typeof import('element-plus-secondary/es')['ElForm']
|
|
||||||
ElFormItem: typeof import('element-plus-secondary/es')['ElFormItem']
|
|
||||||
ElHeader: typeof import('element-plus-secondary/es')['ElHeader']
|
|
||||||
ElIcon: typeof import('element-plus-secondary/es')['ElIcon']
|
ElIcon: typeof import('element-plus-secondary/es')['ElIcon']
|
||||||
ElInput: typeof import('element-plus-secondary/es')['ElInput']
|
|
||||||
ElInputNumber: typeof import('element-plus-secondary/es')['ElInputNumber']
|
|
||||||
ElMain: typeof import('element-plus-secondary/es')['ElMain']
|
|
||||||
ElOption: typeof import('element-plus-secondary/es')['ElOption']
|
|
||||||
ElOptionGroup: typeof import('element-plus-secondary/es')['ElOptionGroup']
|
|
||||||
ElPopover: typeof import('element-plus-secondary/es')['ElPopover']
|
|
||||||
ElRadio: typeof import('element-plus-secondary/es')['ElRadio']
|
|
||||||
ElRadioGroup: typeof import('element-plus-secondary/es')['ElRadioGroup']
|
|
||||||
ElRow: typeof import('element-plus-secondary/es')['ElRow']
|
|
||||||
ElScrollbar: typeof import('element-plus-secondary/es')['ElScrollbar']
|
|
||||||
ElSelect: typeof import('element-plus-secondary/es')['ElSelect']
|
|
||||||
ElSelectV2: typeof import('element-plus-secondary/es')['ElSelectV2']
|
|
||||||
ElSpace: typeof import('element-plus-secondary/es')['ElSpace']
|
|
||||||
ElSwitch: typeof import('element-plus-secondary/es')['ElSwitch']
|
|
||||||
ElTabPane: typeof import('element-plus-secondary/es')['ElTabPane']
|
|
||||||
ElTabs: typeof import('element-plus-secondary/es')['ElTabs']
|
|
||||||
ElTimeline: typeof import('element-plus-secondary/es')['ElTimeline']
|
ElTimeline: typeof import('element-plus-secondary/es')['ElTimeline']
|
||||||
ElTimelineItem: typeof import('element-plus-secondary/es')['ElTimelineItem']
|
ElTimelineItem: typeof import('element-plus-secondary/es')['ElTimelineItem']
|
||||||
ElTimePicker: typeof import('element-plus-secondary/es')['ElTimePicker']
|
|
||||||
ElTooltip: typeof import('element-plus-secondary/es')['ElTooltip']
|
|
||||||
ElTree: typeof import('element-plus-secondary/es')['ElTree']
|
|
||||||
ElTreeSelect: typeof import('element-plus-secondary/es')['ElTreeSelect']
|
|
||||||
ElUpload: typeof import('element-plus-secondary/es')['ElUpload']
|
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
}
|
}
|
||||||
export interface ComponentCustomProperties {
|
|
||||||
vLoading: typeof import('element-plus-secondary/es')['ElLoadingDirective']
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -11,63 +11,65 @@
|
|||||||
"format": "prettier --write src/"
|
"format": "prettier --write src/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"video.js": "^7.21.6",
|
|
||||||
"@videojs-player/vue": "^1.0.0",
|
|
||||||
"@vueuse/core": "^9.13.0",
|
|
||||||
"@npkg/tinymce-plugins": "^0.0.7",
|
|
||||||
"dayjs": "^1.11.9",
|
|
||||||
"flv.js": "^1.6.2",
|
|
||||||
"html2canvas": "^1.4.1",
|
|
||||||
"jspdf": "^2.5.1",
|
|
||||||
"html-to-image": "^1.11.11",
|
|
||||||
"echarts": "^5.5.1",
|
|
||||||
"file-saver": "^2.0.5",
|
|
||||||
"lodash": "^4.17.21",
|
|
||||||
"lodash-es": "^4.17.21",
|
|
||||||
"mathjs": "^11.6.0",
|
|
||||||
"@antv/g2plot": "^2.4.29",
|
"@antv/g2plot": "^2.4.29",
|
||||||
"@antv/l7": "^2.22.0",
|
"@antv/l7": "^2.22.0",
|
||||||
"@antv/l7plot": "^0.5.5",
|
"@antv/l7plot": "^0.5.5",
|
||||||
"@antv/s2": "^1.49.0",
|
"@antv/s2": "^1.49.0",
|
||||||
"vue-i18n": "^9.2.2",
|
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
"@form-create/designer": "^1.1.9",
|
"@form-create/designer": "^1.1.9",
|
||||||
"@form-create/element-ui": "^3.2.22",
|
"@form-create/element-ui": "^3.2.22",
|
||||||
"@form-create/vant": "^3.2.24",
|
"@form-create/vant": "^3.2.24",
|
||||||
"@turf/centroid": "^7.0.0",
|
"@npkg/tinymce-plugins": "^0.0.7",
|
||||||
"@tinymce/tinymce-vue": "^5.1.0",
|
"@tinymce/tinymce-vue": "^5.1.0",
|
||||||
"tinymce": "^5.8.2",
|
"@turf/centroid": "^7.0.0",
|
||||||
|
"@videojs-player/vue": "^1.0.0",
|
||||||
|
"@vueuse/core": "^9.13.0",
|
||||||
"axios": "^1.6.0",
|
"axios": "^1.6.0",
|
||||||
"consola": "^3.4.2",
|
"consola": "^3.4.2",
|
||||||
|
"dayjs": "^1.11.9",
|
||||||
|
"echarts": "^5.5.1",
|
||||||
"element-plus": "^2.4.4",
|
"element-plus": "^2.4.4",
|
||||||
"element-plus-secondary": "^0.6.8",
|
"element-plus-secondary": "^0.6.8",
|
||||||
"element-resize-detector": "^1.2.4",
|
"element-resize-detector": "^1.2.4",
|
||||||
"vuedraggable": "^4.1.0",
|
|
||||||
"exceljs": "^4.4.0",
|
"exceljs": "^4.4.0",
|
||||||
|
"file-saver": "^2.0.5",
|
||||||
|
"flv.js": "^1.6.2",
|
||||||
|
"html-to-image": "^1.11.11",
|
||||||
|
"html2canvas": "^1.4.1",
|
||||||
"js-base64": "^3.7.5",
|
"js-base64": "^3.7.5",
|
||||||
|
"jsencrypt": "^3.3.2",
|
||||||
|
"jspdf": "^2.5.1",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"lodash-es": "^4.17.21",
|
||||||
|
"mathjs": "^11.6.0",
|
||||||
"mitt": "^3.0.0",
|
"mitt": "^3.0.0",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"qs": "^6.11.0",
|
"qs": "^6.11.0",
|
||||||
"screenfull": "^6.0.2",
|
"screenfull": "^6.0.2",
|
||||||
"snowflake-id": "^1.1.0",
|
"snowflake-id": "^1.1.0",
|
||||||
|
"tinymce": "^5.8.2",
|
||||||
"vant": "^4.9.19",
|
"vant": "^4.9.19",
|
||||||
|
"video.js": "^7.21.6",
|
||||||
"vue": "^3.3.4",
|
"vue": "^3.3.4",
|
||||||
|
"vue-i18n": "^9.2.2",
|
||||||
"vue-router": "^4.2.5",
|
"vue-router": "^4.2.5",
|
||||||
"web-storage-cache": "^1.1.1",
|
"vue-types": "^5.0.2",
|
||||||
"vue-types": "^5.0.2"
|
"vue3-sfc-loader": "^0.9.5",
|
||||||
|
"vuedraggable": "^4.1.0",
|
||||||
|
"web-storage-cache": "^1.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
||||||
"@intlify/unplugin-vue-i18n": "^0.8.2",
|
"@intlify/unplugin-vue-i18n": "^0.8.2",
|
||||||
"@rushstack/eslint-patch": "^1.3.3",
|
"@rushstack/eslint-patch": "^1.3.3",
|
||||||
"@vitejs/plugin-vue": "^4.5.2",
|
"@vitejs/plugin-vue": "^4.5.2",
|
||||||
"@vitejs/plugin-vue-jsx": "^4.2.0",
|
"@vitejs/plugin-vue-jsx": "^4.2.0",
|
||||||
"@vue/eslint-config-prettier": "^8.0.0",
|
"@vue/eslint-config-prettier": "^8.0.0",
|
||||||
"less": "^4.1.3",
|
"consola": "^2.15.3",
|
||||||
"jquery": "^3.6.4",
|
|
||||||
"eslint": "^8.49.0",
|
"eslint": "^8.49.0",
|
||||||
"eslint-plugin-vue": "^9.17.0",
|
"eslint-plugin-vue": "^9.17.0",
|
||||||
|
"jquery": "^3.6.4",
|
||||||
|
"less": "^4.1.3",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"sass": "^1.89.0",
|
"sass": "^1.89.0",
|
||||||
"sass-loader": "^16.0.5",
|
"sass-loader": "^16.0.5",
|
||||||
@ -76,7 +78,6 @@
|
|||||||
"unplugin-vue-components-secondary": "^0.24.6",
|
"unplugin-vue-components-secondary": "^0.24.6",
|
||||||
"vite": "^5.0.8",
|
"vite": "^5.0.8",
|
||||||
"vite-plugin-style-import-secondary": "^2.0.0",
|
"vite-plugin-style-import-secondary": "^2.0.0",
|
||||||
"consola": "^2.15.3",
|
|
||||||
"vite-svg-loader": "^5.1.0"
|
"vite-svg-loader": "^5.1.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -54,7 +54,7 @@ export default defineConfig({
|
|||||||
cors: true,
|
cors: true,
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'http://192.168.1.38:8100',
|
target: 'http://192.168.1.58:8080',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
secure: false,
|
secure: false,
|
||||||
rewrite: path => path.replace(/^\/api/, '')
|
rewrite: path => path.replace(/^\/api/, '')
|
||||||
|
Loading…
Reference in New Issue
Block a user