feat(修改): 修改sp6配置待确认
This commit is contained in:
parent
413365dfd1
commit
c57e1e98f5
|
@ -36,7 +36,7 @@ import java.util.stream.Stream;
|
||||||
@Service
|
@Service
|
||||||
public class WebGeneratorCode {
|
public class WebGeneratorCode {
|
||||||
// 公共路径
|
// 公共路径
|
||||||
public static String commonPath = "D:\\MyFolder\\auth-admin\\auth-web\\src";
|
public static String commonPath = "D:\\Project\\web\\PC\\auth\\auth-web\\src";
|
||||||
// 生成API请求路径
|
// 生成API请求路径
|
||||||
public static String apiPath = commonPath + "\\api\\v1\\";
|
public static String apiPath = commonPath + "\\api\\v1\\";
|
||||||
// 生成vue路径
|
// 生成vue路径
|
||||||
|
@ -44,11 +44,11 @@ public class WebGeneratorCode {
|
||||||
// 生成仓库路径
|
// 生成仓库路径
|
||||||
public static String storePath = commonPath + "\\store\\system\\";
|
public static String storePath = commonPath + "\\store\\system\\";
|
||||||
// 后端controller
|
// 后端controller
|
||||||
public static String controllerPath = "D:\\MyFolder\\auth-admin\\auth-server-java\\service\\src\\main\\java\\cn\\bunny\\services\\controller\\";
|
public static String controllerPath = "D:\\Project\\web\\PC\\auth\\auth-server-java\\service\\src\\main\\java\\cn\\bunny\\services\\controller\\";
|
||||||
public static String servicePath = "D:\\MyFolder\\auth-admin\\auth-server-java\\service\\src\\main\\java\\cn\\bunny\\services\\service\\";
|
public static String servicePath = "D:\\Project\\web\\PC\\auth\\auth-server-java\\service\\src\\main\\java\\cn\\bunny\\services\\service\\";
|
||||||
public static String serviceImplPath = "D:\\MyFolder\\auth-admin\\auth-server-java\\service\\src\\main\\java\\cn\\bunny\\services\\service\\impl\\";
|
public static String serviceImplPath = "D:\\Project\\web\\PC\\auth\\auth-server-java\\service\\src\\main\\java\\cn\\bunny\\services\\service\\impl\\";
|
||||||
public static String mapperPath = "D:\\MyFolder\\auth-admin\\auth-server-java\\service\\src\\main\\java\\cn\\bunny\\services\\mapper\\";
|
public static String mapperPath = "D:\\Project\\web\\PC\\auth\\auth-server-java\\service\\src\\main\\java\\cn\\bunny\\services\\mapper\\";
|
||||||
public static String resourceMapperPath = "D:\\MyFolder\\auth-admin\\auth-server-java\\service\\src\\main\\resources\\mapper\\";
|
public static String resourceMapperPath = "D:\\Project\\web\\PC\\auth\\auth-server-java\\service\\src\\main\\resources\\mapper\\";
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
Class<?> originalClass = EmailTemplate.class;
|
Class<?> originalClass = EmailTemplate.class;
|
||||||
|
|
|
@ -46,6 +46,16 @@
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
<version>3.2.3</version>
|
<version>3.2.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.codecentric</groupId>
|
||||||
|
<artifactId>spring-boot-admin-starter-server</artifactId>
|
||||||
|
<version>3.2.3</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.codecentric</groupId>
|
||||||
|
<artifactId>spring-boot-admin-starter-client</artifactId>
|
||||||
|
<version>3.2.3</version>
|
||||||
|
</dependency>
|
||||||
<!-- 单元测试 -->
|
<!-- 单元测试 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package cn.bunny.services;
|
package cn.bunny.services;
|
||||||
|
|
||||||
|
import de.codecentric.boot.admin.server.config.EnableAdminServer;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.mybatis.spring.annotation.MapperScan;
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
|
@ -12,6 +13,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
@MapperScan("cn.bunny.services.mapper")
|
@MapperScan("cn.bunny.services.mapper")
|
||||||
@ComponentScan("cn.bunny")
|
@ComponentScan("cn.bunny")
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
|
@EnableAdminServer
|
||||||
@EnableCaching
|
@EnableCaching
|
||||||
@EnableTransactionManagement
|
@EnableTransactionManagement
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
|
|
@ -26,7 +26,7 @@ import java.util.List;
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Bunny
|
* @author Bunny
|
||||||
* @since 2024-10-10 16:28:29
|
* @since 2024-10-10 21:24:08
|
||||||
*/
|
*/
|
||||||
@Tag(name = "邮件模板表", description = "邮件模板表相关接口")
|
@Tag(name = "邮件模板表", description = "邮件模板表相关接口")
|
||||||
@RestController
|
@RestController
|
||||||
|
|
|
@ -17,11 +17,11 @@ import org.springframework.web.bind.annotation.RestController;
|
||||||
@RequestMapping("/")
|
@RequestMapping("/")
|
||||||
public class IndexController {
|
public class IndexController {
|
||||||
|
|
||||||
@Operation(summary = "访问首页", description = "访问首页")
|
// @Operation(summary = "访问首页", description = "访问首页")
|
||||||
@GetMapping("")
|
// @GetMapping("")
|
||||||
public String index() {
|
// public String index() {
|
||||||
return "欢迎访问 Bunny Java Template,欢迎去Gitee:https://gitee.com/BunnyBoss/java_single.git";
|
// return "欢迎访问 Bunny Java Template,欢迎去Gitee:https://gitee.com/BunnyBoss/java_single.git";
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Operation(summary = "生成验证码", description = "生成验证码")
|
@Operation(summary = "生成验证码", description = "生成验证码")
|
||||||
@GetMapping("noAuth/checkCode")
|
@GetMapping("noAuth/checkCode")
|
||||||
|
|
|
@ -12,6 +12,7 @@ import cn.bunny.dao.pojo.constant.UserConstant;
|
||||||
import cn.bunny.dao.vo.system.user.LoginVo;
|
import cn.bunny.dao.vo.system.user.LoginVo;
|
||||||
import cn.bunny.services.mapper.PowerMapper;
|
import cn.bunny.services.mapper.PowerMapper;
|
||||||
import cn.bunny.services.mapper.RoleMapper;
|
import cn.bunny.services.mapper.RoleMapper;
|
||||||
|
import cn.bunny.services.security.custom.CustomCheckIsAdmin;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
@ -62,16 +63,14 @@ public class UserFactory {
|
||||||
String expires = plusDay.format(dateTimeFormatter);
|
String expires = plusDay.format(dateTimeFormatter);
|
||||||
|
|
||||||
// 查找用户橘色
|
// 查找用户橘色
|
||||||
List<String> roles = roleMapper.selectListByUserId(userId).stream().map(Role::getRoleCode).toList();
|
List<String> roles = new ArrayList<>(roleMapper.selectListByUserId(userId).stream().map(Role::getRoleCode).toList());
|
||||||
List<String> permissions = new ArrayList<>();
|
List<String> permissions = new ArrayList<>();
|
||||||
|
|
||||||
// 判断是否是 admin 如果是admin 赋予所有权限
|
// 判断是否是 admin 如果是admin 赋予所有权限
|
||||||
boolean isAdmin = roles.stream().anyMatch(role -> role.equals("admin"));
|
boolean isAdmin = CustomCheckIsAdmin.checkAdmin(roles, permissions, user);
|
||||||
if (isAdmin) {
|
if (!isAdmin) {
|
||||||
permissions.add("*");
|
permissions = powerMapper.selectListByUserId(userId).stream().map(Power::getPowerCode).toList();
|
||||||
permissions.add("*::*");
|
}
|
||||||
permissions.add("*::*::*");
|
|
||||||
} else permissions = powerMapper.selectListByUserId(userId).stream().map(Power::getPowerCode).toList();
|
|
||||||
|
|
||||||
// 构建返回对象,设置用户需要内容
|
// 构建返回对象,设置用户需要内容
|
||||||
LoginVo loginVo = new LoginVo();
|
LoginVo loginVo = new LoginVo();
|
||||||
|
|
|
@ -16,7 +16,7 @@ import java.util.List;
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Bunny
|
* @author Bunny
|
||||||
* @since 2024-10-10 16:28:29
|
* @since 2024-10-10 21:24:08
|
||||||
*/
|
*/
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface EmailTemplateMapper extends BaseMapper<EmailTemplate> {
|
public interface EmailTemplateMapper extends BaseMapper<EmailTemplate> {
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
package cn.bunny.services.security.config;
|
package cn.bunny.services.security.config;
|
||||||
|
|
||||||
import cn.bunny.services.security.custom.CustomPasswordEncoder;
|
import cn.bunny.services.security.custom.CustomPasswordEncoder;
|
||||||
import cn.bunny.services.security.filter.NoTokenAuthenticationFilter;
|
|
||||||
import cn.bunny.services.security.filter.TokenAuthenticationFilter;
|
|
||||||
import cn.bunny.services.security.filter.TokenLoginFilterService;
|
import cn.bunny.services.security.filter.TokenLoginFilterService;
|
||||||
import cn.bunny.services.security.handelr.SecurityAccessDeniedHandler;
|
import cn.bunny.services.security.handelr.SecurityAccessDeniedHandler;
|
||||||
import cn.bunny.services.security.handelr.SecurityAuthenticationEntryPoint;
|
import cn.bunny.services.security.handelr.SecurityAuthenticationEntryPoint;
|
||||||
import cn.bunny.services.security.service.CustomUserDetailsService;
|
import cn.bunny.services.security.service.CustomUserDetailsService;
|
||||||
import cn.bunny.services.security.service.iml.CustomAuthorizationManagerServiceImpl;
|
import cn.bunny.services.security.service.impl.CustomAuthorizationManagerServiceImpl;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
@ -30,7 +28,7 @@ import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||||
public class WebSecurityConfig {
|
public class WebSecurityConfig {
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private CustomUserDetailsService customUserDetailsService;
|
private CustomUserDetailsService customUserDetailsService;
|
||||||
|
|
||||||
|
@ -49,7 +47,7 @@ public class WebSecurityConfig {
|
||||||
// 前端段分离不需要---禁用明文验证
|
// 前端段分离不需要---禁用明文验证
|
||||||
.httpBasic(AbstractHttpConfigurer::disable)
|
.httpBasic(AbstractHttpConfigurer::disable)
|
||||||
// 前端段分离不需要---禁用默认登录页
|
// 前端段分离不需要---禁用默认登录页
|
||||||
// .formLogin(AbstractHttpConfigurer::disable)
|
.formLogin(AbstractHttpConfigurer::disable)
|
||||||
// 前端段分离不需要---禁用退出页
|
// 前端段分离不需要---禁用退出页
|
||||||
.logout(AbstractHttpConfigurer::disable)
|
.logout(AbstractHttpConfigurer::disable)
|
||||||
// 前端段分离不需要---csrf攻击
|
// 前端段分离不需要---csrf攻击
|
||||||
|
@ -61,6 +59,8 @@ public class WebSecurityConfig {
|
||||||
// 前后端分离不需要---记住我,e -> e.rememberMeParameter("rememberBunny").rememberMeCookieName("rememberBunny").key("BunnyKey")
|
// 前后端分离不需要---记住我,e -> e.rememberMeParameter("rememberBunny").rememberMeCookieName("rememberBunny").key("BunnyKey")
|
||||||
.rememberMe(AbstractHttpConfigurer::disable)
|
.rememberMe(AbstractHttpConfigurer::disable)
|
||||||
.authorizeHttpRequests(authorize -> {
|
.authorizeHttpRequests(authorize -> {
|
||||||
|
// 有样式文件,不需要访问权限
|
||||||
|
authorize.requestMatchers(RegexRequestMatcher.regexMatcher(".*\\.(css|js)$")).permitAll();
|
||||||
// 上面都不是需要鉴权访问
|
// 上面都不是需要鉴权访问
|
||||||
authorize.anyRequest().access(customAuthorizationManagerService);
|
authorize.anyRequest().access(customAuthorizationManagerService);
|
||||||
})
|
})
|
||||||
|
@ -73,8 +73,8 @@ public class WebSecurityConfig {
|
||||||
// 登录验证过滤器
|
// 登录验证过滤器
|
||||||
.addFilterBefore(new TokenLoginFilterService(authenticationConfiguration, redisTemplate, customUserDetailsService), UsernamePasswordAuthenticationFilter.class)
|
.addFilterBefore(new TokenLoginFilterService(authenticationConfiguration, redisTemplate, customUserDetailsService), UsernamePasswordAuthenticationFilter.class)
|
||||||
// 其它权限鉴权过滤器
|
// 其它权限鉴权过滤器
|
||||||
.addFilterAt(new NoTokenAuthenticationFilter(redisTemplate), UsernamePasswordAuthenticationFilter.class)
|
// .addFilterAt(new NoTokenAuthenticationFilter(redisTemplate), UsernamePasswordAuthenticationFilter.class)
|
||||||
.addFilterAt(new TokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
|
// .addFilterAt(new TokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
|
||||||
// 自定义密码加密器和用户登录
|
// 自定义密码加密器和用户登录
|
||||||
.passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService);
|
.passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService);
|
||||||
|
|
||||||
|
@ -92,10 +92,10 @@ public class WebSecurityConfig {
|
||||||
String[] annotations = {
|
String[] annotations = {
|
||||||
"/", "/ws/**",
|
"/", "/ws/**",
|
||||||
"/*/*/noAuth/**", "/*/noAuth/**", "/noAuth/**",
|
"/*/*/noAuth/**", "/*/noAuth/**", "/noAuth/**",
|
||||||
"/media.ico", "/favicon.ico", "*.html", "/webjars/**", "/error", "/*/api-docs/*",
|
"/media.ico", "/favicon.ico", "*.html", "/webjars/**", "/error",
|
||||||
"/*/i18n/getI18n",
|
"/*/i18n/getI18n",
|
||||||
};
|
};
|
||||||
return web -> web.ignoring().requestMatchers(annotations)
|
return web -> web.ignoring().requestMatchers(annotations);
|
||||||
.requestMatchers(RegexRequestMatcher.regexMatcher(".*\\.(css|js)$"));
|
// .requestMatchers(RegexRequestMatcher.regexMatcher(".*\\.(css|js)$"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package cn.bunny.services.security.custom;
|
||||||
|
|
||||||
|
import cn.bunny.dao.entity.system.AdminUser;
|
||||||
|
import cn.bunny.dao.vo.system.user.LoginVo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否是管理员
|
||||||
|
*/
|
||||||
|
public class CustomCheckIsAdmin {
|
||||||
|
|
||||||
|
public static boolean checkAdmin(List<String> roleList, LoginVo loginVo) {
|
||||||
|
// 判断是否是超级管理员
|
||||||
|
if (loginVo.getId().equals(1L)) return true;
|
||||||
|
|
||||||
|
// 判断是否是 admin
|
||||||
|
return roleList.stream().anyMatch(role -> role.equals("admin"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean checkAdmin(List<String> roleList, List<String> permissions, AdminUser adminUser) {
|
||||||
|
// 判断是否是超级管理员
|
||||||
|
boolean isIdAdmin = adminUser.getId().equals(1L);
|
||||||
|
boolean isAdmin = roleList.stream().anyMatch(role -> role.equals("admin"));
|
||||||
|
|
||||||
|
// 判断是否是 admin
|
||||||
|
if (!isIdAdmin || !isAdmin) {
|
||||||
|
roleList.add("admin");
|
||||||
|
permissions.add("*");
|
||||||
|
permissions.add("*::*");
|
||||||
|
permissions.add("*::*::*");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ public class CustomUser extends User {
|
||||||
private AdminUser user;
|
private AdminUser user;
|
||||||
|
|
||||||
public CustomUser(AdminUser user, Collection<? extends GrantedAuthority> authorities) {
|
public CustomUser(AdminUser user, Collection<? extends GrantedAuthority> authorities) {
|
||||||
super(user.getEmail(), user.getPassword(), authorities);
|
super(user.getUsername(), user.getPassword(), authorities);
|
||||||
this.user = user;
|
this.user = user;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -24,7 +24,6 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
||||||
// 自定义实现内容
|
// 自定义实现内容
|
||||||
UsernamePasswordAuthenticationToken authentication = getAuthentication();
|
UsernamePasswordAuthenticationToken authentication = getAuthentication();
|
||||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
|
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
package cn.bunny.services.security.service.iml;
|
|
||||||
|
|
||||||
import cn.bunny.common.service.context.BaseContext;
|
|
||||||
import cn.bunny.dao.entity.system.Power;
|
|
||||||
import cn.bunny.services.mapper.PowerMapper;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.security.authorization.AuthorizationDecision;
|
|
||||||
import org.springframework.security.authorization.AuthorizationManager;
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
|
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定义权限判断
|
|
||||||
* 判断用户有哪些权限
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
@Slf4j
|
|
||||||
public class CustomAuthorizationManagerServiceImpl implements AuthorizationManager<RequestAuthorizationContext> {
|
|
||||||
@Autowired
|
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
|
||||||
@Autowired
|
|
||||||
private PowerMapper powerMapper;
|
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
@Override
|
|
||||||
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) {
|
|
||||||
// 用户的token和用户id、请求Url
|
|
||||||
HttpServletRequest request = context.getRequest();
|
|
||||||
|
|
||||||
// 角色代码列表
|
|
||||||
List<String> roleCodeList = authentication.get().getAuthorities().stream().map(GrantedAuthority::getAuthority).toList();
|
|
||||||
|
|
||||||
// 校验权限
|
|
||||||
return new AuthorizationDecision(hasAuth(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询用户所属的角色信息
|
|
||||||
*
|
|
||||||
* @param request 请求url地址
|
|
||||||
*/
|
|
||||||
private Boolean hasAuth(HttpServletRequest request) {
|
|
||||||
// 角色代码列表
|
|
||||||
List<String> roleCodeList = BaseContext.getLoginVo().getRoles();
|
|
||||||
|
|
||||||
// 判断是否是 admin
|
|
||||||
boolean isAdmin = roleCodeList.stream().anyMatch(role -> role.equals("admin"));
|
|
||||||
if (isAdmin) return true;
|
|
||||||
|
|
||||||
// 不是 admin,查询角色权限关系表
|
|
||||||
List<String> powerCodes = BaseContext.getLoginVo().getPermissions();
|
|
||||||
|
|
||||||
// 根据权限码查询可以访问URL
|
|
||||||
List<Power> powerList = powerMapper.selectListByPowerCodes(powerCodes);
|
|
||||||
|
|
||||||
// 判断是否与请求路径匹配
|
|
||||||
return powerList.stream().anyMatch(power -> AntPathRequestMatcher.antMatcher(power.getRequestUrl()).matches(request) ||
|
|
||||||
request.getRequestURI().matches(power.getRequestUrl()));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
package cn.bunny.services.security.service.impl;
|
||||||
|
|
||||||
|
import cn.bunny.common.service.context.BaseContext;
|
||||||
|
import cn.bunny.common.service.utils.JwtHelper;
|
||||||
|
import cn.bunny.common.service.utils.ResponseUtil;
|
||||||
|
import cn.bunny.dao.entity.system.Power;
|
||||||
|
import cn.bunny.dao.pojo.constant.RedisUserConstant;
|
||||||
|
import cn.bunny.dao.pojo.result.Result;
|
||||||
|
import cn.bunny.dao.pojo.result.ResultCodeEnum;
|
||||||
|
import cn.bunny.dao.vo.system.user.LoginVo;
|
||||||
|
import cn.bunny.services.mapper.PowerMapper;
|
||||||
|
import cn.bunny.services.security.custom.CustomCheckIsAdmin;
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.security.authorization.AuthorizationDecision;
|
||||||
|
import org.springframework.security.authorization.AuthorizationManager;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
|
||||||
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义权限判断
|
||||||
|
* 判断用户有哪些权限
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class CustomAuthorizationManagerServiceImpl implements AuthorizationManager<RequestAuthorizationContext> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PowerMapper powerMapper;
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
@Override
|
||||||
|
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) {
|
||||||
|
// 用户的token和用户id、请求Url
|
||||||
|
HttpServletRequest request = context.getRequest();
|
||||||
|
|
||||||
|
// 是否访问的是接口内容
|
||||||
|
boolean matches = AntPathRequestMatcher.antMatcher("/admin/**").matches(request);
|
||||||
|
if (!matches) return new AuthorizationDecision(true);
|
||||||
|
|
||||||
|
if (checkToken(request)) {
|
||||||
|
return new AuthorizationDecision(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验权限
|
||||||
|
return new AuthorizationDecision(hasAuth(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkToken(HttpServletRequest request) {
|
||||||
|
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse();
|
||||||
|
if (response == null) return false;
|
||||||
|
|
||||||
|
// 判断是否有 token
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
if (token == null) {
|
||||||
|
ResponseUtil.out(response, Result.error(ResultCodeEnum.LOGIN_AUTH));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断 token 是否过期
|
||||||
|
if (JwtHelper.isExpired(token)) {
|
||||||
|
ResponseUtil.out(response, Result.error(ResultCodeEnum.AUTHENTICATION_EXPIRED));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找 Redis
|
||||||
|
String username = JwtHelper.getUsername(token);
|
||||||
|
Long userId = JwtHelper.getUserId(token);
|
||||||
|
Object loginVoObject = redisTemplate.opsForValue().get(RedisUserConstant.getAdminLoginInfoPrefix(username));
|
||||||
|
LoginVo loginVo = JSON.parseObject(JSON.toJSONString(loginVoObject), LoginVo.class);
|
||||||
|
|
||||||
|
// 判断用户是否禁用
|
||||||
|
if (loginVo != null && loginVo.getStatus()) {
|
||||||
|
ResponseUtil.out(response, Result.error(ResultCodeEnum.FAIL_NO_ACCESS_DENIED_USER_LOCKED));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置用户信息
|
||||||
|
BaseContext.setUsername(username);
|
||||||
|
BaseContext.setUserId(userId);
|
||||||
|
BaseContext.setLoginVo(loginVo);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户所属的角色信息
|
||||||
|
*
|
||||||
|
* @param request 请求url地址
|
||||||
|
*/
|
||||||
|
private Boolean hasAuth(HttpServletRequest request) {
|
||||||
|
// 角色代码列表
|
||||||
|
LoginVo loginVo = BaseContext.getLoginVo();
|
||||||
|
List<String> roleCodeList = loginVo.getRoles();
|
||||||
|
|
||||||
|
// 判断是否是管理员用户
|
||||||
|
boolean checkedAdmin = CustomCheckIsAdmin.checkAdmin(roleCodeList, loginVo);
|
||||||
|
if (checkedAdmin) return true;
|
||||||
|
|
||||||
|
// 不是 admin,查询角色权限关系表
|
||||||
|
List<String> powerCodes = loginVo.getPermissions();
|
||||||
|
|
||||||
|
// 根据权限码查询可以访问URL
|
||||||
|
List<Power> powerList = powerMapper.selectListByPowerCodes(powerCodes);
|
||||||
|
|
||||||
|
// 判断是否与请求路径匹配
|
||||||
|
return powerList.stream().anyMatch(power -> AntPathRequestMatcher.antMatcher(power.getRequestUrl()).matches(request) ||
|
||||||
|
request.getRequestURI().matches(power.getRequestUrl()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,8 @@
|
||||||
package cn.bunny.services.security.service.iml;
|
package cn.bunny.services.security.service.impl;
|
||||||
|
|
||||||
import cn.bunny.common.service.exception.BunnyException;
|
import cn.bunny.common.service.exception.BunnyException;
|
||||||
import cn.bunny.dao.dto.system.user.LoginDto;
|
import cn.bunny.dao.dto.system.user.LoginDto;
|
||||||
import cn.bunny.dao.entity.system.AdminUser;
|
import cn.bunny.dao.entity.system.AdminUser;
|
||||||
import cn.bunny.dao.entity.system.Role;
|
|
||||||
import cn.bunny.dao.pojo.result.ResultCodeEnum;
|
import cn.bunny.dao.pojo.result.ResultCodeEnum;
|
||||||
import cn.bunny.dao.vo.system.user.LoginVo;
|
import cn.bunny.dao.vo.system.user.LoginVo;
|
||||||
import cn.bunny.services.factory.UserFactory;
|
import cn.bunny.services.factory.UserFactory;
|
||||||
|
@ -11,7 +10,6 @@ import cn.bunny.services.mapper.RoleMapper;
|
||||||
import cn.bunny.services.mapper.UserMapper;
|
import cn.bunny.services.mapper.UserMapper;
|
||||||
import cn.bunny.services.security.custom.CustomUser;
|
import cn.bunny.services.security.custom.CustomUser;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import lombok.val;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.core.authority.AuthorityUtils;
|
import org.springframework.security.core.authority.AuthorityUtils;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
@ -19,8 +17,6 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.DigestUtils;
|
import org.springframework.util.DigestUtils;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class CustomUserDetailsServiceImpl implements cn.bunny.services.security.service.CustomUserDetailsService {
|
public class CustomUserDetailsServiceImpl implements cn.bunny.services.security.service.CustomUserDetailsService {
|
||||||
|
|
||||||
|
@ -29,24 +25,31 @@ public class CustomUserDetailsServiceImpl implements cn.bunny.services.security.
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserFactory userFactory;
|
private UserFactory userFactory;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RoleMapper roleMapper;
|
private RoleMapper roleMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据用户名获取用户对象(获取不到直接抛异常)
|
||||||
|
*
|
||||||
|
* @param username 用户名
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||||
// 查询用户相关内容
|
// 查询用户相关内容
|
||||||
LambdaQueryWrapper<AdminUser> queryWrapper = new LambdaQueryWrapper<AdminUser>().eq(AdminUser::getEmail, username).or().eq(AdminUser::getUsername, username);
|
LambdaQueryWrapper<AdminUser> queryWrapper = new LambdaQueryWrapper<AdminUser>()
|
||||||
|
.eq(AdminUser::getEmail, username)
|
||||||
|
.or()
|
||||||
|
.eq(AdminUser::getUsername, username);
|
||||||
|
|
||||||
// 根据邮箱查询用户名
|
// 根据邮箱查询用户名
|
||||||
val user = userMapper.selectOne(queryWrapper);
|
AdminUser adminUser = userMapper.selectOne(queryWrapper);
|
||||||
if (user == null) throw new UsernameNotFoundException("用户不存在");
|
if (adminUser == null) throw new UsernameNotFoundException("用户不存在");
|
||||||
|
|
||||||
// 根据用户id查询当前用户所有角色
|
return new CustomUser(adminUser, AuthorityUtils.createAuthorityList());
|
||||||
List<Role> roleList = roleMapper.selectListByUserId(user.getId());
|
|
||||||
List<String> roleCodeList = roleList.stream().map(Role::getRoleCode).toList();
|
|
||||||
return new CustomUser(user, AuthorityUtils.createAuthorityList(roleCodeList));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 前台用户登录接口
|
* 前台用户登录接口
|
||||||
*
|
*
|
|
@ -18,7 +18,7 @@ import java.util.List;
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Bunny
|
* @author Bunny
|
||||||
* @since 2024-10-10 16:28:29
|
* @since 2024-10-10 21:24:08
|
||||||
*/
|
*/
|
||||||
public interface EmailTemplateService extends IService<EmailTemplate> {
|
public interface EmailTemplateService extends IService<EmailTemplate> {
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ import java.util.List;
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Bunny
|
* @author Bunny
|
||||||
* @since 2024-10-10 16:28:29
|
* @since 2024-10-10 21:24:08
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class EmailTemplateServiceImpl extends ServiceImpl<EmailTemplateMapper, EmailTemplate> implements EmailTemplateService {
|
public class EmailTemplateServiceImpl extends ServiceImpl<EmailTemplateMapper, EmailTemplate> implements EmailTemplateService {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import cn.bunny.dao.vo.system.router.UserRouterVo;
|
||||||
import cn.bunny.dao.vo.system.user.LoginVo;
|
import cn.bunny.dao.vo.system.user.LoginVo;
|
||||||
import cn.bunny.services.factory.RouterServiceFactory;
|
import cn.bunny.services.factory.RouterServiceFactory;
|
||||||
import cn.bunny.services.mapper.RouterMapper;
|
import cn.bunny.services.mapper.RouterMapper;
|
||||||
|
import cn.bunny.services.security.custom.CustomCheckIsAdmin;
|
||||||
import cn.bunny.services.service.RouterService;
|
import cn.bunny.services.service.RouterService;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
@ -64,6 +65,7 @@ public class RouterServiceImpl extends ServiceImpl<RouterMapper, Router> impleme
|
||||||
|
|
||||||
// 角色列表
|
// 角色列表
|
||||||
List<String> roleList = loginVo.getRoles();
|
List<String> roleList = loginVo.getRoles();
|
||||||
|
|
||||||
// 权限列表
|
// 权限列表
|
||||||
List<String> powerCodeList = loginVo.getPermissions();
|
List<String> powerCodeList = loginVo.getPermissions();
|
||||||
|
|
||||||
|
@ -74,7 +76,7 @@ public class RouterServiceImpl extends ServiceImpl<RouterMapper, Router> impleme
|
||||||
List<UserRouterVo> list = new ArrayList<>();
|
List<UserRouterVo> list = new ArrayList<>();
|
||||||
|
|
||||||
// 查询用户角色,判断是否是管理员角色
|
// 查询用户角色,判断是否是管理员角色
|
||||||
boolean isAdmin = roleList.stream().anyMatch(authUserRole -> authUserRole.equals("admin"));
|
boolean isAdmin = CustomCheckIsAdmin.checkAdmin(roleList, loginVo);
|
||||||
if (isAdmin) routerList = list();
|
if (isAdmin) routerList = list();
|
||||||
else {
|
else {
|
||||||
List<Long> routerIds = baseMapper.selectListByUserId(loginVo.getId());
|
List<Long> routerIds = baseMapper.selectListByUserId(loginVo.getId());
|
||||||
|
|
|
@ -6,7 +6,7 @@ management:
|
||||||
web:
|
web:
|
||||||
exposure:
|
exposure:
|
||||||
include: "*"
|
include: "*"
|
||||||
base-path: /bunny
|
base-path: /actuator
|
||||||
info:
|
info:
|
||||||
env:
|
env:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
@ -17,6 +17,7 @@ management:
|
||||||
endpoint:
|
endpoint:
|
||||||
health:
|
health:
|
||||||
show-details: always
|
show-details: always
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
profiles:
|
profiles:
|
||||||
active: @profiles.active@
|
active: @profiles.active@
|
||||||
|
@ -25,7 +26,12 @@ spring:
|
||||||
servlet:
|
servlet:
|
||||||
multipart:
|
multipart:
|
||||||
max-file-size: 6MB
|
max-file-size: 6MB
|
||||||
|
boot:
|
||||||
|
admin:
|
||||||
|
client:
|
||||||
|
url: "http://localhost:7070"
|
||||||
|
username: admin
|
||||||
|
password: admin
|
||||||
datasource:
|
datasource:
|
||||||
# type: com.zaxxer.hikari.HikariDataSource
|
# type: com.zaxxer.hikari.HikariDataSource
|
||||||
# driver-class-name: com.mysql.cj.jdbc.Driver
|
# driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
@ -69,6 +75,7 @@ spring:
|
||||||
date-format: yyyy-MM-dd HH:mm:ss
|
date-format: yyyy-MM-dd HH:mm:ss
|
||||||
time-zone: GMT+8
|
time-zone: GMT+8
|
||||||
|
|
||||||
|
|
||||||
# rabbitmq:
|
# rabbitmq:
|
||||||
# host: ${bunny.rabbitmq.host}
|
# host: ${bunny.rabbitmq.host}
|
||||||
# port: ${bunny.rabbitmq.port}
|
# port: ${bunny.rabbitmq.port}
|
||||||
|
|
|
@ -2,11 +2,44 @@
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="cn.bunny.services.mapper.EmailTemplateMapper">
|
<mapper namespace="cn.bunny.services.mapper.EmailTemplateMapper">
|
||||||
|
|
||||||
|
<!-- 通用查询映射结果 -->
|
||||||
|
<resultMap id="BaseResultMap" type="cn.bunny.dao.entity.system.EmailTemplate">
|
||||||
|
<id column="id" property="id"/>
|
||||||
|
<id column="create_time" property="createTime"/>
|
||||||
|
<id column="update_time" property="updateTime"/>
|
||||||
|
<id column="create_user" property="createUser"/>
|
||||||
|
<id column="update_user" property="updateUser"/>
|
||||||
|
<id column="is_deleted" property="isDeleted"/>
|
||||||
|
<id column="template_name" property="templateName"/>
|
||||||
|
<id column="subject" property="subject"/>
|
||||||
|
<id column="body" property="body"/>
|
||||||
|
<id column="type" property="type"/>
|
||||||
|
<id column="is_default" property="isDefault"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<!-- 通用查询结果列 -->
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
id, create_time, update_time, create_user, update_user, is_deleted, template_name, subject, body, type, is_default
|
||||||
|
</sql>
|
||||||
|
|
||||||
<!-- 分页查询邮件模板表内容 -->
|
<!-- 分页查询邮件模板表内容 -->
|
||||||
<select id="selectListByPage" resultType="cn.bunny.dao.entity.system.EmailTemplate">
|
<select id="selectListByPage" resultType="cn.bunny.dao.entity.system.EmailTemplate">
|
||||||
select * from $tableName
|
select
|
||||||
|
<include refid="Base_Column_List"/>
|
||||||
|
from sys_email_template
|
||||||
<where>
|
<where>
|
||||||
|
<if test="dto.templateName != null and dto.templateName != ''">
|
||||||
|
template_name like CONCAT('%',#{dto.templateName},'%')
|
||||||
|
</if>
|
||||||
|
<if test="dto.subject != null and dto.subject != ''">
|
||||||
|
subject like CONCAT('%',#{dto.subject},'%')
|
||||||
|
</if>
|
||||||
|
<if test="dto.body != null and dto.body != ''">
|
||||||
|
body like CONCAT('%',#{dto.body},'%')
|
||||||
|
</if>
|
||||||
|
<if test="dto.type != null and dto.type != ''">
|
||||||
|
type like CONCAT('%',#{dto.type},'%')
|
||||||
|
</if>
|
||||||
</where>
|
</where>
|
||||||
order by update_time desc
|
order by update_time desc
|
||||||
</select>
|
</select>
|
||||||
|
@ -14,7 +47,7 @@
|
||||||
<!-- 物理删除邮件模板表 -->
|
<!-- 物理删除邮件模板表 -->
|
||||||
<delete id="deleteBatchIdsWithPhysics">
|
<delete id="deleteBatchIdsWithPhysics">
|
||||||
delete
|
delete
|
||||||
from $tableName
|
from sys_email_template
|
||||||
where id in
|
where id in
|
||||||
<foreach collection="ids" item="id" open="(" close=")" separator=",">
|
<foreach collection="ids" item="id" open="(" close=")" separator=",">
|
||||||
#{id}
|
#{id}
|
||||||
|
|
Loading…
Reference in New Issue