fix: 修改部分bug和缺陷
This commit is contained in:
parent
65685d6cd9
commit
151a2027ae
|
@ -15,6 +15,7 @@ logs/
|
||||||
.springBeans
|
.springBeans
|
||||||
.sts4-cache
|
.sts4-cache
|
||||||
|
|
||||||
|
application-prod.yml
|
||||||
|
|
||||||
### IntelliJ IDEA ###
|
### IntelliJ IDEA ###
|
||||||
.idea
|
.idea
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
# 感谢
|
||||||
|
|
||||||
|
项目由[小铭](https://github.com/xiaoxian521)开源权限模板[Pure-admin](https://pure-admin.github.io/vue-pure-admin/)
|
||||||
|
|
||||||
|
Pure-admin文档:https://pure-admin.github.io/pure-admin-doc
|
||||||
|
|
||||||
|
项目整体都由此模板开发
|
||||||
|
|
||||||
# 项目预览
|
# 项目预览
|
||||||
|
|
||||||
不知道为什么,图床用的使自己的,Gitee就是不显示其它GitHub和Gitea都能显示就Gitee显示不出来,如果想用Gitee就把ReadMe文件下载下来也行;或者把项目clone下来看也可以
|
不知道为什么,图床用的使自己的,Gitee就是不显示其它GitHub和Gitea都能显示就Gitee显示不出来,如果想用Gitee就把ReadMe文件下载下来也行;或者把项目clone下来看也可以
|
||||||
|
|
|
@ -3,11 +3,11 @@ package cn.bunny.common.generator.generator;
|
||||||
import cn.bunny.common.generator.entity.BaseField;
|
import cn.bunny.common.generator.entity.BaseField;
|
||||||
import cn.bunny.common.generator.entity.BaseResultMap;
|
import cn.bunny.common.generator.entity.BaseResultMap;
|
||||||
import cn.bunny.common.generator.utils.GeneratorCodeUtils;
|
import cn.bunny.common.generator.utils.GeneratorCodeUtils;
|
||||||
import cn.bunny.dao.dto.financial.category.CategoryAddDto;
|
import cn.bunny.dao.dto.system.user.AdminUserAddDto;
|
||||||
import cn.bunny.dao.dto.financial.category.CategoryDto;
|
import cn.bunny.dao.dto.system.user.AdminUserDto;
|
||||||
import cn.bunny.dao.dto.financial.category.CategoryUpdateDto;
|
import cn.bunny.dao.dto.system.user.AdminUserUpdateDto;
|
||||||
import cn.bunny.dao.entity.financial.Category;
|
import cn.bunny.dao.entity.system.AdminUser;
|
||||||
import cn.bunny.dao.vo.financial.CategoryVo;
|
import cn.bunny.dao.vo.system.user.AdminUserVo;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.google.common.base.CaseFormat;
|
import com.google.common.base.CaseFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
@ -52,11 +52,11 @@ public class WebGeneratorCode {
|
||||||
public static String resourceMapperPath = "D:\\MyFolder\\financial\\financial-server\\service\\src\\main\\resources\\mapper\\financial\\";
|
public static String resourceMapperPath = "D:\\MyFolder\\financial\\financial-server\\service\\src\\main\\resources\\mapper\\financial\\";
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
Class<?> originalClass = Category.class;
|
Class<?> originalClass = AdminUser.class;
|
||||||
Class<?> dtoClass = CategoryDto.class;
|
Class<?> dtoClass = AdminUserDto.class;
|
||||||
Class<?> addDtoClass = CategoryAddDto.class;
|
Class<?> addDtoClass = AdminUserAddDto.class;
|
||||||
Class<?> updateDtoClass = CategoryUpdateDto.class;
|
Class<?> updateDtoClass = AdminUserUpdateDto.class;
|
||||||
Class<?> voClass = CategoryVo.class;
|
Class<?> voClass = AdminUserVo.class;
|
||||||
|
|
||||||
// 设置velocity资源加载器
|
// 设置velocity资源加载器
|
||||||
Properties prop = new Properties();
|
Properties prop = new Properties();
|
||||||
|
|
|
@ -27,7 +27,7 @@ ENTRYPOINT ["java","-jar","/home/server/app.jar"]
|
||||||
#暴露 8000 端口
|
#暴露 8000 端口
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
# 开发环境
|
# 生产环境
|
||||||
# mvn clean package -Pprod -DskipTests
|
# mvn clean package -Pprod -DskipTests
|
||||||
|
|
||||||
# 测试环境
|
# 测试环境
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
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;
|
||||||
|
@ -16,7 +14,6 @@ import org.springframework.security.config.annotation.authentication.configurati
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||||
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.annotation.web.configuration.WebSecurityCustomizer;
|
|
||||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||||
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;
|
||||||
|
@ -43,6 +40,12 @@ public class WebSecurityConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
|
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
|
||||||
|
String[] annotations = {
|
||||||
|
"/", "/ws/**",
|
||||||
|
"/*/*/noAuth/**", "/*/noAuth/**", "/noAuth/**",
|
||||||
|
"/media.ico", "/favicon.ico", "*.html", "/webjars/**", "/v3/api-docs/**", "swagger-ui/**",
|
||||||
|
"/error", "/*/i18n/getI18n",
|
||||||
|
};
|
||||||
httpSecurity
|
httpSecurity
|
||||||
// 前端段分离不需要---禁用明文验证
|
// 前端段分离不需要---禁用明文验证
|
||||||
.httpBasic(AbstractHttpConfigurer::disable)
|
.httpBasic(AbstractHttpConfigurer::disable)
|
||||||
|
@ -56,9 +59,11 @@ public class WebSecurityConfig {
|
||||||
.cors(AbstractHttpConfigurer::disable)
|
.cors(AbstractHttpConfigurer::disable)
|
||||||
// 前后端分离不需要---因为是无状态的
|
// 前后端分离不需要---因为是无状态的
|
||||||
.sessionManagement(AbstractHttpConfigurer::disable)
|
.sessionManagement(AbstractHttpConfigurer::disable)
|
||||||
// 前后端分离不需要---记住我,e -> e.rememberMeParameter("rememberBunny").rememberMeCookieName("rememberBunny").key("BunnyKey")
|
// 前后端分离不需要---记住我
|
||||||
.rememberMe(AbstractHttpConfigurer::disable)
|
.rememberMe(AbstractHttpConfigurer::disable)
|
||||||
.authorizeHttpRequests(authorize -> authorize.anyRequest().access(customAuthorizationManagerService))
|
.authorizeHttpRequests(authorize -> authorize.requestMatchers(annotations).permitAll()
|
||||||
|
.requestMatchers(RegexRequestMatcher.regexMatcher(".*\\.(css|js)$")).permitAll()
|
||||||
|
.anyRequest().access(customAuthorizationManagerService))
|
||||||
.exceptionHandling(exception -> {
|
.exceptionHandling(exception -> {
|
||||||
// 请求未授权接口
|
// 请求未授权接口
|
||||||
exception.authenticationEntryPoint(new SecurityAuthenticationEntryPoint());
|
exception.authenticationEntryPoint(new SecurityAuthenticationEntryPoint());
|
||||||
|
@ -67,25 +72,9 @@ 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 TokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
|
|
||||||
// 自定义密码加密器和用户登录
|
// 自定义密码加密器和用户登录
|
||||||
.passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService);
|
.passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService);
|
||||||
|
|
||||||
return httpSecurity.build();
|
return httpSecurity.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 排出鉴定路径
|
|
||||||
@Bean
|
|
||||||
public WebSecurityCustomizer webSecurityCustomizer() {
|
|
||||||
String[] annotations = {
|
|
||||||
"/", "/ws/**",
|
|
||||||
"/*/*/noAuth/**", "/*/noAuth/**", "/noAuth/**",
|
|
||||||
"/media.ico", "/favicon.ico", "*.html", "/webjars/**", "/v3/api-docs/**", "swagger-ui/**",
|
|
||||||
"/error", "/*/i18n/getI18n",
|
|
||||||
};
|
|
||||||
return web -> web.ignoring().requestMatchers(annotations)
|
|
||||||
.requestMatchers(RegexRequestMatcher.regexMatcher(".*\\.(css|js)$"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
package cn.bunny.services.security.filter;
|
|
||||||
|
|
||||||
|
|
||||||
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.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 com.alibaba.fastjson2.JSON;
|
|
||||||
import jakarta.servlet.FilterChain;
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class NoTokenAuthenticationFilter extends OncePerRequestFilter {
|
|
||||||
private final RedisTemplate<String, Object> redisTemplate;
|
|
||||||
|
|
||||||
public NoTokenAuthenticationFilter(RedisTemplate<String, Object> redisTemplate) {
|
|
||||||
this.redisTemplate = redisTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doFilterInternal(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException {
|
|
||||||
// 判断是否有 token
|
|
||||||
String token = request.getHeader("token");
|
|
||||||
if (token == null) {
|
|
||||||
ResponseUtil.out(response, Result.error(ResultCodeEnum.LOGIN_AUTH));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断 token 是否过期
|
|
||||||
if (JwtHelper.isExpired(token)) {
|
|
||||||
ResponseUtil.out(response, Result.error(ResultCodeEnum.AUTHENTICATION_EXPIRED));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析JWT中的用户名
|
|
||||||
String username = JwtHelper.getUsername(token);
|
|
||||||
Long userId = JwtHelper.getUserId(token);
|
|
||||||
|
|
||||||
// 查找 Redis
|
|
||||||
Object loginVoObject = redisTemplate.opsForValue().get(RedisUserConstant.getAdminLoginInfoPrefix(username));
|
|
||||||
LoginVo loginVo = JSON.parseObject(JSON.toJSONString(loginVoObject), LoginVo.class);
|
|
||||||
|
|
||||||
// 登录信息为空
|
|
||||||
if (loginVo == null) {
|
|
||||||
ResponseUtil.out(response, Result.error(ResultCodeEnum.LOGIN_AUTH));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断用户是否禁用
|
|
||||||
if (loginVo.getStatus()) {
|
|
||||||
ResponseUtil.out(response, Result.error(ResultCodeEnum.FAIL_NO_ACCESS_DENIED_USER_LOCKED));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置用户信息
|
|
||||||
BaseContext.setUsername(username);
|
|
||||||
BaseContext.setUserId(userId);
|
|
||||||
BaseContext.setLoginVo(loginVo);
|
|
||||||
|
|
||||||
// 执行下一个过滤器
|
|
||||||
doFilter(request, response, filterChain);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
package cn.bunny.services.security.filter;
|
|
||||||
|
|
||||||
import cn.bunny.common.service.context.BaseContext;
|
|
||||||
import cn.bunny.dao.vo.system.user.LoginVo;
|
|
||||||
import jakarta.servlet.FilterChain;
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doFilterInternal(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
|
|
||||||
// 自定义实现内容
|
|
||||||
UsernamePasswordAuthenticationToken authentication = getAuthentication();
|
|
||||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
|
||||||
chain.doFilter(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户请求判断
|
|
||||||
*
|
|
||||||
* @return 验证码方法
|
|
||||||
*/
|
|
||||||
private UsernamePasswordAuthenticationToken getAuthentication() {
|
|
||||||
// 请求头是否有token
|
|
||||||
LoginVo loginVo = BaseContext.getLoginVo();
|
|
||||||
String username = loginVo.getUsername();
|
|
||||||
List<String> roleList = loginVo.getRoles();
|
|
||||||
|
|
||||||
// 角色列表
|
|
||||||
List<SimpleGrantedAuthority> authList = roleList.stream().map(SimpleGrantedAuthority::new).toList();
|
|
||||||
|
|
||||||
if (authList.isEmpty()) return new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
|
|
||||||
return new UsernamePasswordAuthenticationToken(username, null, authList);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -16,7 +16,7 @@ import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||||
@Override
|
@Override
|
||||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) {
|
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) {
|
||||||
String token = response.getHeader("token");
|
String token = request.getHeader("token");
|
||||||
String message = authException.getMessage();
|
String message = authException.getMessage();
|
||||||
// 创建结果对象
|
// 创建结果对象
|
||||||
Result<Object> result;
|
Result<Object> result;
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
package cn.bunny.services.security.service.impl;
|
package cn.bunny.services.security.service.impl;
|
||||||
|
|
||||||
import cn.bunny.common.service.context.BaseContext;
|
import cn.bunny.common.service.context.BaseContext;
|
||||||
|
import cn.bunny.common.service.utils.JwtHelper;
|
||||||
import cn.bunny.dao.entity.system.Power;
|
import cn.bunny.dao.entity.system.Power;
|
||||||
import cn.bunny.dao.entity.system.Role;
|
import cn.bunny.dao.entity.system.Role;
|
||||||
|
import cn.bunny.dao.pojo.constant.RedisUserConstant;
|
||||||
|
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 cn.bunny.services.security.custom.CustomCheckIsAdmin;
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.AuthorizationDecision;
|
||||||
import org.springframework.security.authorization.AuthorizationManager;
|
import org.springframework.security.authorization.AuthorizationManager;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
@ -36,12 +41,49 @@ public class CustomAuthorizationManagerServiceImpl implements AuthorizationManag
|
||||||
@Autowired
|
@Autowired
|
||||||
private RoleMapper roleMapper;
|
private RoleMapper roleMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@Override
|
@Override
|
||||||
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) {
|
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) {
|
||||||
// 用户的token和用户id、请求Url
|
// 用户的token和用户id、请求Url
|
||||||
HttpServletRequest request = context.getRequest();
|
HttpServletRequest request = context.getRequest();
|
||||||
|
|
||||||
|
// 判断是否有 token
|
||||||
|
String token = request.getHeader("token");
|
||||||
|
if (token == null) {
|
||||||
|
return new AuthorizationDecision(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断 token 是否过期
|
||||||
|
if (JwtHelper.isExpired(token)) {
|
||||||
|
return new AuthorizationDecision(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析JWT中的用户名
|
||||||
|
String username = JwtHelper.getUsername(token);
|
||||||
|
Long userId = JwtHelper.getUserId(token);
|
||||||
|
|
||||||
|
// 查找 Redis
|
||||||
|
Object loginVoObject = redisTemplate.opsForValue().get(RedisUserConstant.getAdminLoginInfoPrefix(username));
|
||||||
|
LoginVo loginVo = JSON.parseObject(JSON.toJSONString(loginVoObject), LoginVo.class);
|
||||||
|
|
||||||
|
// 登录信息为空
|
||||||
|
if (loginVo == null) {
|
||||||
|
return new AuthorizationDecision(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断用户是否禁用
|
||||||
|
if (loginVo.getStatus()) {
|
||||||
|
return new AuthorizationDecision(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置用户信息
|
||||||
|
BaseContext.setUsername(username);
|
||||||
|
BaseContext.setUserId(userId);
|
||||||
|
BaseContext.setLoginVo(loginVo);
|
||||||
|
|
||||||
// 校验权限
|
// 校验权限
|
||||||
return new AuthorizationDecision(hasAuth(request));
|
return new AuthorizationDecision(hasAuth(request));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue