This commit is contained in:
lixiaodong 2023-07-13 20:15:41 +08:00
parent 54d8d9489a
commit ac6921a278
11 changed files with 102 additions and 65 deletions

View File

@ -4,13 +4,8 @@ import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaRouter; import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import net.lab1024.sa.common.config.UrlConfig; import net.lab1024.sa.common.config.UrlConfig;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
/** /**
* sa-token 配置 * sa-token 配置
@ -19,25 +14,21 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
* @date 2023/7/13 16:57 * @date 2023/7/13 16:57
*/ */
@Configuration @Configuration
public class SaTokenConfig implements WebMvcConfigurer { public class SaTokenConfig {
/** /**
* 注册 Sa-Token 拦截器定义详细认证规则 * 定义 Sa-Token 拦截器定义详细认证规则
*
* @param registry
*/ */
@Override @Bean
public void addInterceptors(InterceptorRegistry registry) { public SaInterceptor saInterceptor() {
SaInterceptor interceptor = new SaInterceptor(handler -> {
// 每个路由 都做为一个权限点
UrlConfig.URL_LIST.forEach(url -> SaRouter.match(url, r -> StpUtil.checkPermission(url)));
});
// 关闭注解鉴权 只做路由拦截校验 // 关闭注解鉴权 只做路由拦截校验
interceptor.isAnnotation(false); return new SaInterceptor(handler -> {
registry.addInterceptor(interceptor).addPathPatterns("/**"); /**
* 每个路由 都做为一个权限点
* TODO listen from定义的api
* from menu数据表已选择的api
*/
UrlConfig.AUTH_URL_LIST.forEach(url -> SaRouter.match(url, r -> StpUtil.checkPermission(url)));
}).isAnnotation(false);
} }
} }

View File

@ -1,12 +1,18 @@
package net.lab1024.sa.admin.module.system.employee.service; package net.lab1024.sa.admin.module.system.employee.service;
import cn.dev33.satoken.stp.StpInterface;
import net.lab1024.sa.admin.module.system.employee.dao.EmployeeDao;
import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity;
import net.lab1024.sa.admin.module.system.menu.constant.MenuTypeEnum;
import net.lab1024.sa.admin.module.system.menu.domain.vo.MenuVO; import net.lab1024.sa.admin.module.system.menu.domain.vo.MenuVO;
import net.lab1024.sa.admin.module.system.role.service.RoleEmployeeService; import net.lab1024.sa.admin.module.system.role.service.RoleEmployeeService;
import net.lab1024.sa.admin.module.system.role.service.RoleMenuService; import net.lab1024.sa.admin.module.system.role.service.RoleMenuService;
import net.lab1024.sa.common.module.support.token.TokenService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
* 员工权限校验 * 员工权限校验
@ -18,7 +24,7 @@ import java.util.List;
* @Copyright 1024创新实验室 https://1024lab.net * @Copyright 1024创新实验室 https://1024lab.net
*/ */
@Service @Service
public class EmployeePermissionService { public class EmployeePermissionService implements StpInterface {
@Autowired @Autowired
private RoleEmployeeService roleEmployeeService; private RoleEmployeeService roleEmployeeService;
@ -26,6 +32,9 @@ public class EmployeePermissionService {
@Autowired @Autowired
private RoleMenuService roleMenuService; private RoleMenuService roleMenuService;
@Autowired
private EmployeeDao employeeDao;
/** /**
* 查询用户拥有的前端菜单项 用于登陆返回 前端动态路由配置 * 查询用户拥有的前端菜单项 用于登陆返回 前端动态路由配置
* *
@ -37,4 +46,20 @@ public class EmployeePermissionService {
return roleMenuService.getMenuList(roleIdList, administratorFlag); return roleMenuService.getMenuList(roleIdList, administratorFlag);
} }
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
Long employeeId = TokenService.getUserId((String) loginId);
// TODO listen 待做权限缓存
EmployeeEntity employeeEntity = employeeDao.selectById(employeeId);
List<MenuVO> menuList = this.getEmployeeMenuAndPointsList(employeeId, employeeEntity.getAdministratorFlag());
return menuList.stream()
.filter(e -> MenuTypeEnum.POINTS.equalsValue(e.getMenuType()))
.map(MenuVO::getApiPerms).distinct().collect(Collectors.toList());
}
@Override
public List<String> getRoleList(Object loginId, String loginType) {
return null;
}
} }

View File

@ -1,6 +1,5 @@
package net.lab1024.sa.admin.module.system.login.controller; package net.lab1024.sa.admin.module.system.login.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.extra.servlet.ServletUtil;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
@ -13,7 +12,6 @@ import net.lab1024.sa.common.common.constant.RequestHeaderConst;
import net.lab1024.sa.common.common.domain.ResponseDTO; import net.lab1024.sa.common.common.domain.ResponseDTO;
import net.lab1024.sa.common.common.util.SmartRequestUtil; import net.lab1024.sa.common.common.util.SmartRequestUtil;
import net.lab1024.sa.common.module.support.captcha.domain.CaptchaVO; import net.lab1024.sa.common.module.support.captcha.domain.CaptchaVO;
import org.checkerframework.checker.units.qual.N;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -58,20 +56,8 @@ public class LoginController {
@ApiOperation("获取登录结果信息 @author 卓大") @ApiOperation("获取登录结果信息 @author 卓大")
@GetMapping("/login/getLoginInfo") @GetMapping("/login/getLoginInfo")
public ResponseDTO<LoginEmployeeDetail> getLoginInfo() { public ResponseDTO<LoginEmployeeDetail> getLoginInfo() {
/* Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); LoginEmployeeDetail loginEmployeeDetail = loginService.getLoginUserDetailCache(SmartRequestUtil.getUserId());
if (authentication == null) { return ResponseDTO.ok(loginEmployeeDetail);
return ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID);
}
Object principal = authentication.getPrincipal();
if (!(principal instanceof LoginEmployeeDetail)) {
return ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID);
}
LoginEmployeeDetail loginEmployeeDetail = (LoginEmployeeDetail) authentication.getPrincipal();
loginEmployeeDetail.setLoginPassword(null);
return ResponseDTO.ok(loginEmployeeDetail);*/
return ResponseDTO.ok();
} }
@ApiOperation("退出登录 @author 卓大") @ApiOperation("退出登录 @author 卓大")

View File

@ -93,7 +93,7 @@ public class LoginService {
// 校验 图形验证码 // 校验 图形验证码
ResponseDTO<String> checkCaptcha = captchaService.checkCaptcha(loginForm); ResponseDTO<String> checkCaptcha = captchaService.checkCaptcha(loginForm);
if (!checkCaptcha.getOk()) { if (!checkCaptcha.getOk()) {
// TODO listen 待放开 return ResponseDTO.error(checkCaptcha); // TODO listen 待放开 return ResponseDTO.error(checkCaptcha);
} }
/** /**
@ -160,7 +160,7 @@ public class LoginService {
List<MenuVO> menuAndPointsList = employeePermissionService.getEmployeeMenuAndPointsList(employeeEntity.getEmployeeId(), employeeEntity.getAdministratorFlag()); List<MenuVO> menuAndPointsList = employeePermissionService.getEmployeeMenuAndPointsList(employeeEntity.getEmployeeId(), employeeEntity.getAdministratorFlag());
//前端菜单 //前端菜单
loginEmployeeDetail.setMenuList(menuAndPointsList); loginEmployeeDetail.setMenuList(menuAndPointsList);
//后端权限 // TODO listen 原先为什么返回权限
// loginEmployeeDetail.setAuthorities(employeePermissionService.buildAuthorities(menuAndPointsList)); // loginEmployeeDetail.setAuthorities(employeePermissionService.buildAuthorities(menuAndPointsList));
//上次登录信息 //上次登录信息
@ -195,6 +195,15 @@ public class LoginService {
loginLogService.log(loginEntity); loginLogService.log(loginEntity);
} }
/**
* 查询用户信息缓存
*
* @param requestUserId
*/
public LoginEmployeeDetail getLoginUserDetailCache(Long requestUserId) {
return loginUserDetailCache.get(requestUserId);
}
/** /**
* 移除用户信息缓存 * 移除用户信息缓存

View File

@ -20,7 +20,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -39,6 +38,10 @@ public class MenuService {
@Autowired @Autowired
private MenuDao menuDao; private MenuDao menuDao;
@Autowired
private List<RequestUrlVO> authUrl;
/** /**
* 添加菜单 * 添加菜单
* *
@ -281,8 +284,7 @@ public class MenuService {
* @return * @return
*/ */
public ResponseDTO<List<RequestUrlVO>> getAuthUrl() { public ResponseDTO<List<RequestUrlVO>> getAuthUrl() {
// TODO listen return ResponseDTO.ok(authUrl);
return ResponseDTO.ok(Collections.emptyList());
} }
} }

View File

@ -77,9 +77,9 @@ public class RoleMenuService {
* @param roleIdList * @param roleIdList
* @return * @return
*/ */
public List<MenuVO> getMenuList(List<Long> roleIdList, Boolean administratorFlag) { public List<MenuVO> getMenuList(List<Long> roleIdList, Boolean adminFlag) {
//理员返回所有菜单 // 管返回所有菜单
if(administratorFlag){ if(adminFlag){
List<MenuEntity> menuEntityList = roleMenuDao.selectMenuListByRoleIdList(Lists.newArrayList(), false); List<MenuEntity> menuEntityList = roleMenuDao.selectMenuListByRoleIdList(Lists.newArrayList(), false);
return SmartBeanUtil.copyList(menuEntityList, MenuVO.class); return SmartBeanUtil.copyList(menuEntityList, MenuVO.class);
} }

View File

@ -19,7 +19,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Objects;
/** /**
* 抽象拦截器 * 抽象拦截器

View File

@ -1,5 +1,6 @@
package net.lab1024.sa.common.config; package net.lab1024.sa.common.config;
import cn.dev33.satoken.interceptor.SaInterceptor;
import net.lab1024.sa.common.common.interceptor.AbstractInterceptor; import net.lab1024.sa.common.common.interceptor.AbstractInterceptor;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -26,14 +27,24 @@ public class MvcConfig implements WebMvcConfigurer {
@Autowired(required = false) @Autowired(required = false)
private List<AbstractInterceptor> interceptorList; private List<AbstractInterceptor> interceptorList;
@Autowired(required = false)
private List<SaInterceptor> saInterceptorList;
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
if (CollectionUtils.isEmpty(interceptorList)) { // 先注册 登录拦截器
return; if (CollectionUtils.isNotEmpty(interceptorList)) {
interceptorList.forEach(e -> {
registry.addInterceptor(e).addPathPatterns(e.pathPatterns()).excludePathPatterns(e.getIgnoreUrlList());
});
}
// 后注册 sa-token 权限拦截器 不需要可以删除
if (CollectionUtils.isNotEmpty(saInterceptorList)) {
saInterceptorList.forEach(i -> {
registry.addInterceptor(i).addPathPatterns("/**");
});
} }
interceptorList.forEach(e -> {
registry.addInterceptor(e).addPathPatterns(e.pathPatterns()).excludePathPatterns(e.getIgnoreUrlList());
});
} }
@Override @Override

View File

@ -34,7 +34,7 @@ public class UrlConfig {
@Autowired @Autowired
private RequestMappingHandlerMapping requestMappingHandlerMapping; private RequestMappingHandlerMapping requestMappingHandlerMapping;
public static List<String> URL_LIST = Lists.newArrayList(); public static List<String> AUTH_URL_LIST = Lists.newArrayList();
/** /**
* 获取每个方法的请求路径 * 获取每个方法的请求路径
@ -74,8 +74,15 @@ public class UrlConfig {
if (null != ignore) { if (null != ignore) {
continue; continue;
} }
List<RequestUrlVO> requestUrlList = this.buildRequestUrl(method, entry.getValue()); NoNeedLogin noNeedLogin = method.getAnnotation(NoNeedLogin.class);
if (null != noNeedLogin) {
continue;
}
Set<String> urlSet = entry.getValue();
List<RequestUrlVO> requestUrlList = this.buildRequestUrl(method, urlSet);
authUrlList.addAll(requestUrlList); authUrlList.addAll(requestUrlList);
AUTH_URL_LIST.addAll(urlSet);
} }
log.info("需要权限校验的URL{}", authUrlList.stream().map(RequestUrlVO::getUrl).collect(Collectors.toList())); log.info("需要权限校验的URL{}", authUrlList.stream().map(RequestUrlVO::getUrl).collect(Collectors.toList()));
return authUrlList; return authUrlList;
@ -98,8 +105,6 @@ public class UrlConfig {
requestUrlVO.setUrl(url); requestUrlVO.setUrl(url);
requestUrlVO.setComment(methodComment); requestUrlVO.setComment(methodComment);
requestUrlList.add(requestUrlVO); requestUrlList.add(requestUrlVO);
URL_LIST.add(url);
} }
return requestUrlList; return requestUrlList;
} }

View File

@ -9,13 +9,10 @@ import org.springframework.stereotype.Component;
import java.util.List; import java.util.List;
/** /**
* 与用户token的相关的服务 * 用户token 相关服务
* *
* @Author 1024创新实验室-主任: 卓大 * @author listen
* @Date 2021-11-29 19:48:35 * @date 2023-07-12 22:48:35
* @Wechat zhuoda1024
* @Email lab1024@163.com
* @Copyright 1024创新实验室 https://1024lab.net
*/ */
@Component @Component
public class TokenService { public class TokenService {
@ -63,6 +60,10 @@ public class TokenService {
return Long.valueOf(loginId.substring(loginId.indexOf(StringConst.HORIZONTAL) + 1)); return Long.valueOf(loginId.substring(loginId.indexOf(StringConst.HORIZONTAL) + 1));
} }
public static Integer getUserType(String loginId) {
return Integer.valueOf(loginId.substring(0, loginId.indexOf(StringConst.HORIZONTAL)));
}
/** /**
* 退出登录 注销 * 退出登录 注销
*/ */

View File

@ -131,12 +131,20 @@ sa-token:
# token 有效期(单位:秒) 默认30天-1 代表永久有效 # token 有效期(单位:秒) 默认30天-1 代表永久有效
timeout: 2592000 timeout: 2592000
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
active-timeout: 28800 active-timeout: -1
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录) # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
is-concurrent: false is-concurrent: false
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token(jwt模式下恒false) # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token(jwt模式下恒false)
is-share: false is-share: false
# token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik(jwt模式下无用) # token 风格默认可取值uuid、simple-uuid、random-32、random-64、random-128、tik(jwt模式下无用)
token-style: simple-uuid token-style: simple-uuid
# 是否打开自动续签 如果此值为true框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作)
auto-renew: true
# 是否输出操作日志 # 是否输出操作日志
is-log: true is-log: true
# 日志等级trace、debug、info、warn、error、fatal
log-level: debug
# 启动时的字符画打印
is-print: false
# 是否从cookie读取token
is-read-cookie: false