fix: 修改部分bug和缺陷
This commit is contained in:
parent
65685d6cd9
commit
151a2027ae
|
@ -15,6 +15,7 @@ logs/
|
|||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
application-prod.yml
|
||||
|
||||
### IntelliJ 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下来看也可以
|
||||
|
|
|
@ -3,11 +3,11 @@ package cn.bunny.common.generator.generator;
|
|||
import cn.bunny.common.generator.entity.BaseField;
|
||||
import cn.bunny.common.generator.entity.BaseResultMap;
|
||||
import cn.bunny.common.generator.utils.GeneratorCodeUtils;
|
||||
import cn.bunny.dao.dto.financial.category.CategoryAddDto;
|
||||
import cn.bunny.dao.dto.financial.category.CategoryDto;
|
||||
import cn.bunny.dao.dto.financial.category.CategoryUpdateDto;
|
||||
import cn.bunny.dao.entity.financial.Category;
|
||||
import cn.bunny.dao.vo.financial.CategoryVo;
|
||||
import cn.bunny.dao.dto.system.user.AdminUserAddDto;
|
||||
import cn.bunny.dao.dto.system.user.AdminUserDto;
|
||||
import cn.bunny.dao.dto.system.user.AdminUserUpdateDto;
|
||||
import cn.bunny.dao.entity.system.AdminUser;
|
||||
import cn.bunny.dao.vo.system.user.AdminUserVo;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.google.common.base.CaseFormat;
|
||||
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 void main(String[] args) throws Exception {
|
||||
Class<?> originalClass = Category.class;
|
||||
Class<?> dtoClass = CategoryDto.class;
|
||||
Class<?> addDtoClass = CategoryAddDto.class;
|
||||
Class<?> updateDtoClass = CategoryUpdateDto.class;
|
||||
Class<?> voClass = CategoryVo.class;
|
||||
Class<?> originalClass = AdminUser.class;
|
||||
Class<?> dtoClass = AdminUserDto.class;
|
||||
Class<?> addDtoClass = AdminUserAddDto.class;
|
||||
Class<?> updateDtoClass = AdminUserUpdateDto.class;
|
||||
Class<?> voClass = AdminUserVo.class;
|
||||
|
||||
// 设置velocity资源加载器
|
||||
Properties prop = new Properties();
|
||||
|
|
|
@ -27,7 +27,7 @@ ENTRYPOINT ["java","-jar","/home/server/app.jar"]
|
|||
#暴露 8000 端口
|
||||
EXPOSE 8000
|
||||
|
||||
# 开发环境
|
||||
# 生产环境
|
||||
# mvn clean package -Pprod -DskipTests
|
||||
|
||||
# 测试环境
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package cn.bunny.services.security.config;
|
||||
|
||||
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.handelr.SecurityAccessDeniedHandler;
|
||||
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.web.builders.HttpSecurity;
|
||||
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.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
@ -43,6 +40,12 @@ public class WebSecurityConfig {
|
|||
|
||||
@Bean
|
||||
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
|
||||
// 前端段分离不需要---禁用明文验证
|
||||
.httpBasic(AbstractHttpConfigurer::disable)
|
||||
|
@ -56,9 +59,11 @@ public class WebSecurityConfig {
|
|||
.cors(AbstractHttpConfigurer::disable)
|
||||
// 前后端分离不需要---因为是无状态的
|
||||
.sessionManagement(AbstractHttpConfigurer::disable)
|
||||
// 前后端分离不需要---记住我,e -> e.rememberMeParameter("rememberBunny").rememberMeCookieName("rememberBunny").key("BunnyKey")
|
||||
// 前后端分离不需要---记住我
|
||||
.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 -> {
|
||||
// 请求未授权接口
|
||||
exception.authenticationEntryPoint(new SecurityAuthenticationEntryPoint());
|
||||
|
@ -67,25 +72,9 @@ public class WebSecurityConfig {
|
|||
})
|
||||
// 登录验证过滤器
|
||||
.addFilterBefore(new TokenLoginFilterService(authenticationConfiguration, redisTemplate, customUserDetailsService), UsernamePasswordAuthenticationFilter.class)
|
||||
// 其它权限鉴权过滤器
|
||||
.addFilterAt(new NoTokenAuthenticationFilter(redisTemplate), UsernamePasswordAuthenticationFilter.class)
|
||||
.addFilterAt(new TokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
|
||||
// 自定义密码加密器和用户登录
|
||||
.passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService);
|
||||
|
||||
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 {
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) {
|
||||
String token = response.getHeader("token");
|
||||
String token = request.getHeader("token");
|
||||
String message = authException.getMessage();
|
||||
// 创建结果对象
|
||||
Result<Object> result;
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
package cn.bunny.services.security.service.impl;
|
||||
|
||||
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.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.RoleMapper;
|
||||
import cn.bunny.services.security.custom.CustomCheckIsAdmin;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
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;
|
||||
|
@ -36,12 +41,49 @@ public class CustomAuthorizationManagerServiceImpl implements AuthorizationManag
|
|||
@Autowired
|
||||
private RoleMapper roleMapper;
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) {
|
||||
// 用户的token和用户id、请求Url
|
||||
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));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue