diff --git a/sgzb-auth/src/main/java/com/bonus/sgzb/auth/controller/TokenController.java b/sgzb-auth/src/main/java/com/bonus/sgzb/auth/controller/TokenController.java index f1a61e6..0dc9be5 100644 --- a/sgzb-auth/src/main/java/com/bonus/sgzb/auth/controller/TokenController.java +++ b/sgzb-auth/src/main/java/com/bonus/sgzb/auth/controller/TokenController.java @@ -26,6 +26,9 @@ import com.bonus.sgzb.common.security.utils.SecurityUtils; import com.bonus.sgzb.system.api.model.LoginUser; import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; /** * token 控制 @@ -107,14 +110,58 @@ public class TokenController { } @PostMapping("checkCode") - public R checkCode(@RequestBody LoginBody form) { + public R checkCode(@RequestBody LoginBody form, HttpServletRequest request) { + String ip = request.getRemoteAddr(); + String ipKey = "ip_" + ip; + + // 获取当前IP的请求次数,默认为0 + int requestCount = 0; + try { + String countStr = redisService.getCacheObject(ipKey); + if (countStr != null) { + requestCount = Integer.parseInt(countStr); + } + } catch (NumberFormatException e) { + log.error("Failed to parse request count for IP: {}", ip, e); + return R.fail(null, "系统错误,请稍后再试"); + } + + // 检查请求次数是否超过限制 + if (requestCount >= 3) { + return R.fail(null, "您的请求过于频繁,请稍后再试"); + } + + // 增加请求次数并设置过期时间 + redisService.setCacheObject(ipKey, String.valueOf(requestCount + 1), 60L, TimeUnit.MINUTES); + + // 使用ScheduledExecutorService替代Timer,避免资源泄漏 + ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); + scheduler.schedule(() -> { + try { + String currentCountStr = redisService.getCacheObject(ipKey); + if (currentCountStr != null) { + int currentCount = Integer.parseInt(currentCountStr); + if (currentCount > 0) { + redisService.setCacheObject(ipKey, String.valueOf(currentCount - 1)); + } + } + } catch (NumberFormatException e) { + log.error("Failed to decrement request count for IP: {}", ip, e); + } + }, 60, TimeUnit.SECONDS); + + // 验证码校验 + if (StringUtils.isBlank(form.getPhone()) || StringUtils.isBlank(form.getCode())) { + return R.fail(null, "手机号或验证码不能为空"); + } + // 校验验证码 LoginUser loginUser = sysLoginService.loginCode(form.getPhone(), form.getCode()); if (StringUtils.isNotNull(loginUser)) { loginUser.setLoginMethod("mobile"); // 创建token Map tokenMap = tokenService.createToken(loginUser); - return R.ok(tokenService.createToken(loginUser)); + return R.ok(tokenMap); } else { return R.fail(null, "验证码错误"); } diff --git a/sgzb-auth/src/main/java/com/bonus/sgzb/auth/service/SysLoginService.java b/sgzb-auth/src/main/java/com/bonus/sgzb/auth/service/SysLoginService.java index 0ff43bb..91d3d24 100644 --- a/sgzb-auth/src/main/java/com/bonus/sgzb/auth/service/SysLoginService.java +++ b/sgzb-auth/src/main/java/com/bonus/sgzb/auth/service/SysLoginService.java @@ -123,7 +123,7 @@ public class SysLoginService { if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) { recordLogService.recordLogininfor(phone, Constants.LOGIN_FAIL, "登录手机号不存在"); - throw new ServiceException("登录手机号:" + phone + " 不存在"); + throw new ServiceException("登录信息:" + phone + " 错误"); } if (R.FAIL == userResult.getCode()) { diff --git a/sgzb-auth/src/main/resources/bootstrap-sgzb_nw_dev.yml b/sgzb-auth/src/main/resources/bootstrap-sgzb_nw_dev.yml new file mode 100644 index 0000000..1061a55 --- /dev/null +++ b/sgzb-auth/src/main/resources/bootstrap-sgzb_nw_dev.yml @@ -0,0 +1,40 @@ +# Spring +spring: + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: 127.0.0.1:8848 + namespace: sgzb_nwjj + config: + # 配置中心地址 + server-addr: 127.0.0.1:8848 + namespace: sgzb_nwjj + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + +onlineApprove: /lbcloud-oauth/oauth/token +wechatAppId: crhmaxnE +wechatAppsecret: 3893e6ed90d325f00e34583dd970a56580c05549 +getNowPersonDetailData: /lbcloud-user/user/queryLoginUserInfo +baseUrl: https://test-sso.csgmall.com.cn +appAppsecret: d8e6db9fa9bb09da0e270fa739233c823bf9c5f0 +personEasyList: /lbcloud-user/api/user/queryAndPaging/basicInfo +h5Appsecret: 3c4a67b7f6a268b4202a5328e6a1726979d5903b +h5AppId: G3NksDH2 +appsecret: 596e4863c8d112842ce820c130b236001297ea73 +appId: akvVFYgy +appAppId: u8LLfynf +getPersonDetailData: /lbcloud-user/api/user/queryById +registerPhone: /lbcloud-user/api/user/registrationByPhone +userBindUrl: /lbcloud-authority/api/RoleClient/bindDefaultSystemRole +verifyPhoneCode: /lbcloud-mbroker/api/broker/simpleVerificationCode + +# 禁用Actuator端点的未经身份验证的访问 +management: + endpoint: + env: + enabled: false \ No newline at end of file diff --git a/sgzb-auth/src/main/resources/bootstrap.yml b/sgzb-auth/src/main/resources/bootstrap.yml index 0117fe0..e2f472b 100644 --- a/sgzb-auth/src/main/resources/bootstrap.yml +++ b/sgzb-auth/src/main/resources/bootstrap.yml @@ -9,4 +9,4 @@ spring: name: sgzb-auth profiles: # 环境配置 - active: sgzb_cq_local + active: sgzb_nw_dev diff --git a/sgzb-common/sgzb-common-security/pom.xml b/sgzb-common/sgzb-common-security/pom.xml index 5e07dc3..dfcf60e 100644 --- a/sgzb-common/sgzb-common-security/pom.xml +++ b/sgzb-common/sgzb-common-security/pom.xml @@ -37,7 +37,7 @@ cn.hutool hutool-all - 4.6.16 + 5.8.24 com.alibaba.fastjson2 diff --git a/sgzb-gateway/pom.xml b/sgzb-gateway/pom.xml index ef290ad..03c144a 100644 --- a/sgzb-gateway/pom.xml +++ b/sgzb-gateway/pom.xml @@ -94,6 +94,14 @@ jasypt-spring-boot-starter 3.0.2 + + org.springframework.security + spring-security-config + + + org.springframework.security + spring-security-web + diff --git a/sgzb-gateway/src/main/java/com/bonus/sgzb/gateway/config/Swagger2SecurityConfig.java b/sgzb-gateway/src/main/java/com/bonus/sgzb/gateway/config/Swagger2SecurityConfig.java new file mode 100644 index 0000000..f91ca24 --- /dev/null +++ b/sgzb-gateway/src/main/java/com/bonus/sgzb/gateway/config/Swagger2SecurityConfig.java @@ -0,0 +1,31 @@ +package com.bonus.sgzb.gateway.config; + +/** + * @author : syruan + * @version : 1.0 + * @PackagePath: com.bonus.sgzb.gateway.config + * @CreateTime: 2025-02-12 16:28 + * @Description: swagger配置类 + */ +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.web.server.SecurityWebFilterChain; + +import static org.springframework.security.config.Customizer.withDefaults; + +@EnableWebFluxSecurity +public class Swagger2SecurityConfig { + + @Bean + public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { + return http + .authorizeExchange(exchanges -> exchanges + .pathMatchers("/swagger-ui/**", "/v2/api-docs/**").authenticated() + .anyExchange().permitAll() + ) + .httpBasic(withDefaults()) + .csrf().disable() + .build(); + } +} diff --git a/sgzb-gateway/src/main/resources/bootstrap-sgzb_nw_dev.yml b/sgzb-gateway/src/main/resources/bootstrap-sgzb_nw_dev.yml new file mode 100644 index 0000000..5c4ed63 --- /dev/null +++ b/sgzb-gateway/src/main/resources/bootstrap-sgzb_nw_dev.yml @@ -0,0 +1,70 @@ +# Spring +spring: + servlet: + multipart: + max-request-size: 50MB + max-file-size: 30MB + cloud: + loadbalancer: + # 关闭Ribbon的负载均衡器 + ribbon: + enabled: false + # 开启Nacos的负载均衡器 + nacos: + enabled: true + nacos: + discovery: + # 服务注册地址 + server-addr: 127.0.0.1:8848 + namespace: sgzb_nwjj + config: + # 配置中心地址 + server-addr: 127.0.0.1:8848 + namespace: sgzb_nwjj + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + +#腾讯云sms +tencent: + sms: + #api秘钥标识 + accessKeyId: AKIDrreCVaRKDtMcgfU5QW9iEfv67tMfldJn + #api秘钥 + accessKeySecret: OXUgeMo0yhBRTGo6sVu3yiFX4rQtAzc3 + #请求域名 + endpoint: sms.tencentcloudapi.com + #所属区域 + region: ap-guangzhou + #腾讯云申请应用id + sdkAppId: 1400494336 + #签名 + smsSign: 南方电网互联网 + #云平台模板id 2116937-验收通知 2115503-登录验证 + templateId: 2116937,2115503 + # 腾讯云cos + cos: + file: + # 存储桶所在地域 + region: ap-guangzhou + # 存储桶所在地域 + bucketregion: ap-guangzhou + # 存储桶名称 + bucketname: prod-rental-1301524038 + # API账号 + secretid: AKIDrreCVaRKDtMcgfU5QW9iEfv67tMfldJn + # API密钥 + secretkey: OXUgeMo0yhBRTGo6sVu3yiFX4rQtAzc3 + +# 禁用Actuator端点的未经身份验证的访问 +management: + endpoint: + env: + enabled: false + + + + + diff --git a/sgzb-gateway/src/main/resources/bootstrap.yml b/sgzb-gateway/src/main/resources/bootstrap.yml index c26d13d..65880ed 100644 --- a/sgzb-gateway/src/main/resources/bootstrap.yml +++ b/sgzb-gateway/src/main/resources/bootstrap.yml @@ -9,4 +9,4 @@ spring: name: sgzb-gateway profiles: # 环境配置 - active: sgzb_cq_local + active: sgzb_nw_dev diff --git a/sgzb-modules/sgzb-material/pom.xml b/sgzb-modules/sgzb-material/pom.xml index d9759c0..7d0dbbc 100644 --- a/sgzb-modules/sgzb-material/pom.xml +++ b/sgzb-modules/sgzb-material/pom.xml @@ -41,12 +41,12 @@ ch.qos.logback logback-core - 1.2.13 + 1.3.15 ch.qos.logback logback-classic - 1.2.13 + 1.3.15 diff --git a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/controller/SysFileController.java b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/controller/SysFileController.java index d3b2158..a61976d 100644 --- a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/controller/SysFileController.java +++ b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/controller/SysFileController.java @@ -2,6 +2,7 @@ package com.bonus.sgzb.system.controller; import com.bonus.sgzb.common.core.utils.StringHelper; import com.bonus.sgzb.common.core.web.domain.AjaxResult; +import com.bonus.sgzb.common.security.annotation.RequiresPermissions; import com.bonus.sgzb.system.domain.FileInfo; import com.bonus.sgzb.system.service.SysFileService; import io.swagger.annotations.ApiOperation; @@ -57,11 +58,14 @@ public class SysFileController { @ApiOperation(value = "模板", httpMethod = "GET") @GetMapping("download") + @RequiresPermissions("system:file:download") // 权限标识符 public void download(HttpServletRequest request, HttpServletResponse response, String filename) { InputStream inputStream = null; ServletOutputStream servletOutputStream = null; try { String path = "download/" + filename; + // 防止路径被绕过、目录穿越 + path = path.replaceAll("\\.\\.", "").replaceAll("\\.", "").replaceAll("/", ""); org.springframework.core.io.Resource resource = resourceLoader.getResource("classpath:" + path); response.setContentType("application/vnd.ms-excel"); response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate"); diff --git a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/service/impl/SysSmsServiceImpl.java b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/service/impl/SysSmsServiceImpl.java index 8e2b157..577f602 100644 --- a/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/service/impl/SysSmsServiceImpl.java +++ b/sgzb-modules/sgzb-system/src/main/java/com/bonus/sgzb/system/service/impl/SysSmsServiceImpl.java @@ -3,12 +3,16 @@ package com.bonus.sgzb.system.service.impl; import cn.hutool.http.HttpRequest; import com.alibaba.druid.util.StringUtils; import com.alibaba.fastjson.JSONObject; +import com.bonus.sgzb.common.core.constant.SecurityConstants; import com.bonus.sgzb.common.core.constant.UserConstants; +import com.bonus.sgzb.common.core.domain.R; import com.bonus.sgzb.common.core.exception.ServiceException; import com.bonus.sgzb.common.core.utils.GlobalConstants; import com.bonus.sgzb.common.core.web.domain.AjaxResult; import com.bonus.sgzb.common.redis.service.RedisService; +import com.bonus.sgzb.system.api.RemoteUserService; import com.bonus.sgzb.system.api.domain.SysUser; +import com.bonus.sgzb.system.api.model.LoginUser; import com.bonus.sgzb.system.config.TencentSmsConfig; import com.bonus.sgzb.system.mapper.SysUserMapper; import com.bonus.sgzb.system.service.ISysSmsService; @@ -27,6 +31,7 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.Random; import java.util.concurrent.TimeUnit; @@ -45,12 +50,16 @@ public class SysSmsServiceImpl implements ISysSmsService { @Resource private RedisService redisService; + @Resource private SysUserMapper sysUserMapper; @Resource private TencentSmsConfig tencentSmsConfig; + @Resource + private RemoteUserService remoteUserService; + /** * 短信URL @@ -79,6 +88,12 @@ public class SysSmsServiceImpl implements ISysSmsService { } catch (Exception e) { return AjaxResult.error("发送失败:" + e.getMessage()); }*/ + // 查询用户信息 + R userResult = remoteUserService.getUserInfoByPhone(phone, SecurityConstants.INNER); + if (Objects.isNull(userResult) || Objects.isNull(userResult.getData())) { + return AjaxResult.error("手机号码不正确"); + } + return sendMsgByPhone(phone, msg); } diff --git a/sgzb-modules/sgzb-system/src/main/resources/bootstrap-sgzb_nw_dev.yml b/sgzb-modules/sgzb-system/src/main/resources/bootstrap-sgzb_nw_dev.yml new file mode 100644 index 0000000..5c4ed63 --- /dev/null +++ b/sgzb-modules/sgzb-system/src/main/resources/bootstrap-sgzb_nw_dev.yml @@ -0,0 +1,70 @@ +# Spring +spring: + servlet: + multipart: + max-request-size: 50MB + max-file-size: 30MB + cloud: + loadbalancer: + # 关闭Ribbon的负载均衡器 + ribbon: + enabled: false + # 开启Nacos的负载均衡器 + nacos: + enabled: true + nacos: + discovery: + # 服务注册地址 + server-addr: 127.0.0.1:8848 + namespace: sgzb_nwjj + config: + # 配置中心地址 + server-addr: 127.0.0.1:8848 + namespace: sgzb_nwjj + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + +#腾讯云sms +tencent: + sms: + #api秘钥标识 + accessKeyId: AKIDrreCVaRKDtMcgfU5QW9iEfv67tMfldJn + #api秘钥 + accessKeySecret: OXUgeMo0yhBRTGo6sVu3yiFX4rQtAzc3 + #请求域名 + endpoint: sms.tencentcloudapi.com + #所属区域 + region: ap-guangzhou + #腾讯云申请应用id + sdkAppId: 1400494336 + #签名 + smsSign: 南方电网互联网 + #云平台模板id 2116937-验收通知 2115503-登录验证 + templateId: 2116937,2115503 + # 腾讯云cos + cos: + file: + # 存储桶所在地域 + region: ap-guangzhou + # 存储桶所在地域 + bucketregion: ap-guangzhou + # 存储桶名称 + bucketname: prod-rental-1301524038 + # API账号 + secretid: AKIDrreCVaRKDtMcgfU5QW9iEfv67tMfldJn + # API密钥 + secretkey: OXUgeMo0yhBRTGo6sVu3yiFX4rQtAzc3 + +# 禁用Actuator端点的未经身份验证的访问 +management: + endpoint: + env: + enabled: false + + + + + diff --git a/sgzb-modules/sgzb-system/src/main/resources/bootstrap.yml b/sgzb-modules/sgzb-system/src/main/resources/bootstrap.yml index b24ca0b..48d99c7 100644 --- a/sgzb-modules/sgzb-system/src/main/resources/bootstrap.yml +++ b/sgzb-modules/sgzb-system/src/main/resources/bootstrap.yml @@ -9,4 +9,4 @@ spring: name: sgzb-system profiles: # 环境配置 - active: sgzb_cq_local + active: sgzb_nw_dev