diff --git a/gym-manage-api/gym-member/pom.xml b/gym-manage-api/gym-member/pom.xml
index c74a4c3..2f57396 100644
--- a/gym-manage-api/gym-member/pom.xml
+++ b/gym-manage-api/gym-member/pom.xml
@@ -27,6 +27,11 @@
manage-db
${project.version}
+
+ cn.novalon.gym.manage
+ manage-sys
+ ${project.version}
+
org.springframework.boot
spring-boot-starter-webflux
@@ -108,26 +113,12 @@
com.github.binarywang
weixin-java-miniapp
4.6.0
-
+
+
com.github.binarywang
weixin-java-mp
4.6.0
-
-
- io.jsonwebtoken
- jjwt-api
-
-
- io.jsonwebtoken
- jjwt-impl
- runtime
-
-
- io.jsonwebtoken
- jjwt-jackson
- runtime
-
cn.hutool
hutool-all
diff --git a/gym-manage-api/gym-member/src/main/java/cn/novalon/gym/manage/member/handler/MemberHandler.java b/gym-manage-api/gym-member/src/main/java/cn/novalon/gym/manage/member/handler/MemberHandler.java
index fbd6e99..4d66c7a 100644
--- a/gym-manage-api/gym-member/src/main/java/cn/novalon/gym/manage/member/handler/MemberHandler.java
+++ b/gym-manage-api/gym-member/src/main/java/cn/novalon/gym/manage/member/handler/MemberHandler.java
@@ -8,12 +8,11 @@ import cn.novalon.gym.manage.member.service.MemberService;
import cn.novalon.gym.manage.member.service.WechatAuthService;
import cn.novalon.gym.manage.member.service.WechatOfficialService;
import cn.novalon.gym.manage.member.util.AesUtil;
+import cn.novalon.gym.manage.member.util.AuthUtil;
import cn.novalon.gym.manage.sys.security.JwtTokenProvider;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
@@ -37,6 +36,7 @@ public class MemberHandler {
private final WechatOfficialService wechatOfficialService;
private final JwtTokenProvider jwtTokenProvider;
private final WechatProperties wechatProperties;
+ private final AuthUtil authUtil;
/**
* 获取会员信息
@@ -46,10 +46,7 @@ public class MemberHandler {
*/
public Mono getMemberInfo(ServerRequest request) {
- String memberIdStr = request.headers().firstHeader("X-Member-Id");
- long memberId = NumberUtils.toLong(memberIdStr,0L);
-
- if (memberId <= 0) throw new IllegalArgumentException("获取会员信息失败: memberId 无效");
+ Long memberId = authUtil.getMemberIdOrThrow(request);
log.info("获取会员信息, memberId: {}", memberId);
@@ -76,10 +73,7 @@ public class MemberHandler {
*/
public Mono updateMemberInfo(ServerRequest request) {
- String memberIdStr = request.headers().firstHeader("X-Member-Id");
- long memberId = NumberUtils.toLong(memberIdStr, 0L);
-
- if (memberId <= 0) throw new IllegalArgumentException("更新会员信息失败: memberId 无效");
+ Long memberId = authUtil.getMemberIdOrThrow(request);
log.info("更新会员信息, memberId: {}", memberId);
@@ -98,14 +92,11 @@ public class MemberHandler {
*/
public Mono bindPhone(ServerRequest request) {
- String memberIdStr = request.headers().firstHeader("X-Member-Id");
- Long memberId = NumberUtils.toLong(memberIdStr, 0L);
-
- if (memberId <= 0) throw new IllegalArgumentException("绑定手机号失败: memberId 无效");
+ Long memberId = authUtil.getMemberIdOrThrow(request);
String phoneCode = request.queryParam("phoneCode").orElse("");
- if (phoneCode == null || phoneCode.trim().isEmpty()) throw new IllegalArgumentException("手机号code不能为空");
+ if (phoneCode.trim().isEmpty()) throw new IllegalArgumentException("手机号code不能为空");
log.info("收到绑定手机号请求, memberId: {}, phoneCode: {}", memberId, phoneCode);
@@ -124,10 +115,7 @@ public class MemberHandler {
*/
public Mono checkSubscribeStatus(ServerRequest request) {
- String memberIdStr = request.headers().firstHeader("X-Member-Id");
- long memberId = NumberUtils.toLong(memberIdStr,0L);
-
- if (memberId <= 0) throw new IllegalArgumentException("查询服务号关注状态失败: memberId 无效");
+ Long memberId = authUtil.getMemberIdOrThrow(request);
log.info("查询服务号关注状态, memberId: {}", memberId);
@@ -148,6 +136,8 @@ public class MemberHandler {
*/
public Mono adminUpdatePhone(ServerRequest request) {
+ Long adminId = authUtil.getMemberIdOrThrow(request);
+
String memberIdStr = request.pathVariable("id");
long memberId = NumberUtils.toLong(memberIdStr, 0L);
@@ -184,18 +174,12 @@ public class MemberHandler {
*/
public Mono adminGetMemberInfo(ServerRequest request) {
- String authorization = request.headers().firstHeader(HttpHeaders.AUTHORIZATION);
- if (authorization == null || !authorization.startsWith("Bearer ")) throw new IllegalArgumentException("无权访问");
- authorization = authorization.substring(7);
- // 验证token并获取memberId
- if (!jwtTokenProvider.validateToken(authorization)) throw new IllegalArgumentException("Authorization 无效");
+ Long adminId = authUtil.getMemberIdOrThrow(request);
String memberIdStr = request.pathVariable("id");
long memberId = NumberUtils.toLong(memberIdStr, 0L);
if(memberId <= 0) throw new IllegalArgumentException("会员ID格式错误");
- Long adminId = jwtTokenProvider.getUserIdFromToken(authorization);
-
// TODO 多表查询:会员信息、团课信息、会员卡信息
return ServerResponse.ok()
@@ -212,17 +196,11 @@ public class MemberHandler {
*/
public Mono adminUpdateMemberInfo(ServerRequest request) {
- String authorization = request.headers().firstHeader(HttpHeaders.AUTHORIZATION);
- if (authorization == null || !authorization.startsWith("Bearer ")) throw new IllegalArgumentException("无权访问");
- authorization = authorization.substring(7);
- // 验证token并获取memberId
- if (!jwtTokenProvider.validateToken(authorization)) throw new IllegalArgumentException("Authorization 无效");
+ Long adminId = authUtil.getMemberIdOrThrow(request);
String memberIdStr = request.pathVariable("id");
long memberId = NumberUtils.toLong(memberIdStr, 0L);
- if(memberId <= 0) throw new IllegalArgumentException("会员ID格式错误");
-
- Long adminId = jwtTokenProvider.getUserIdFromToken(authorization);
+ if(memberId <= 0L) throw new IllegalArgumentException("会员ID格式错误");
// TODO 多表查询:会员信息、团课信息、会员卡信息
@@ -239,14 +217,7 @@ public class MemberHandler {
*/
public Mono searchMembers(ServerRequest request) {
- String authorization = request.headers().firstHeader(HttpHeaders.AUTHORIZATION);
- if (authorization == null || !authorization.startsWith("Bearer ")) {
- return ServerResponse.status(HttpStatus.UNAUTHORIZED).bodyValue("无权访问");
- }
- authorization = authorization.substring(7);
- if (!jwtTokenProvider.validateToken(authorization)) {
- return ServerResponse.status(HttpStatus.UNAUTHORIZED).bodyValue("Authorization 无效");
- }
+ Long adminId = authUtil.getMemberIdOrThrow(request);
String keyword = request.queryParam("searchValue").orElse(null);
String filter = request.queryParam("filter").orElse(null);
@@ -282,14 +253,7 @@ public class MemberHandler {
*/
public Mono getAllMembers(ServerRequest request) {
- String authorization = request.headers().firstHeader(HttpHeaders.AUTHORIZATION);
- if (authorization == null || !authorization.startsWith("Bearer ")) {
- return ServerResponse.status(HttpStatus.UNAUTHORIZED).bodyValue("无权访问");
- }
- authorization = authorization.substring(7);
- if (!jwtTokenProvider.validateToken(authorization)) {
- return ServerResponse.status(HttpStatus.UNAUTHORIZED).bodyValue("Authorization 无效");
- }
+ Long adminId = authUtil.getMemberIdOrThrow(request);
int pageNum = NumberUtils.toInt(request.queryParam("pageNum").orElse("1"), 1);
int pageSize = NumberUtils.toInt(request.queryParam("pageSize").orElse("10"), 10);
diff --git a/gym-manage-api/gym-member/src/main/java/cn/novalon/gym/manage/member/service/impl/WechatAuthServiceImpl.java b/gym-manage-api/gym-member/src/main/java/cn/novalon/gym/manage/member/service/impl/WechatAuthServiceImpl.java
index 1a858d7..5d7904f 100644
--- a/gym-manage-api/gym-member/src/main/java/cn/novalon/gym/manage/member/service/impl/WechatAuthServiceImpl.java
+++ b/gym-manage-api/gym-member/src/main/java/cn/novalon/gym/manage/member/service/impl/WechatAuthServiceImpl.java
@@ -1,6 +1,5 @@
package cn.novalon.gym.manage.member.service.impl;
-import cn.novalon.gym.manage.common.config.JwtProperties;
import cn.novalon.gym.manage.member.config.WechatProperties;
import cn.novalon.gym.manage.member.dto.WechatLoginDto;
import cn.novalon.gym.manage.member.entity.Member;
@@ -14,20 +13,16 @@ import cn.novalon.gym.manage.member.util.EsSyncUtils;
import cn.novalon.gym.manage.member.util.MemberNoGenerator;
import cn.novalon.gym.manage.member.util.WechatPhoneUtil;
import cn.novalon.gym.manage.member.vo.WechatLoginVO;
-import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.security.Keys;
+import cn.novalon.gym.manage.sys.security.JwtTokenProvider;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
-import javax.crypto.SecretKey;
-import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
/**
* 微信认证服务实现
@@ -43,11 +38,11 @@ public class WechatAuthServiceImpl implements WechatAuthService {
private final WechatApiService wechatApiService;
private final IMemberRepository memberRepository;
- private final JwtProperties jwtProperties;
private final WechatProperties wechatProperties;
private final WechatPhoneUtil wechatPhoneUtil;
private final MemberESRepository memberESRepository;
private final EsSyncUtils esSyncUtils;
+ private final JwtTokenProvider jwtTokenProvider;
private EsSyncUtils.EntitySyncer memberSyncer;
@@ -332,60 +327,23 @@ public class WechatAuthServiceImpl implements WechatAuthService {
member.getPhone() != null ? "已绑定" : "未绑定");
}
- // 生成 Access Token(使用 Gateway 相同的方式)
- String accessToken = generateJwtToken(member.getId(), "access");
- // 生成 Refresh Token(有效期更长)
- String refreshToken = generateJwtToken(member.getId(), "refresh", 7L * 24 * 60 * 60 * 1000);
+ // 统一使用 JwtTokenProvider 生成 Token
+ // 使用空的角色列表,会员不需要角色
+ List roles = new ArrayList<>();
+ String accessToken = jwtTokenProvider.generateToken(String.valueOf(member.getId()), member.getId(), roles);
log.info("JWT Token 生成成功, memberId: {}", member.getId());
- // 计算过期时间(秒)
- long expiresIn = jwtProperties.getExpiration() / 1000;
+ // 使用 JwtTokenProvider 默认过期时间(86400 秒)
+ int expiresIn = 86400;
return WechatLoginVO.builder()
.memberId(member.getId())
.accessToken(accessToken)
- .refreshToken(refreshToken)
- .expiresIn((int) expiresIn)
+ .refreshToken(accessToken)
+ .expiresIn(expiresIn)
.isNewUser(isNewUser)
.needCompleteInfo(needCompleteInfo)
.build();
}
-
- /**
- * 生成 JWT Token(与 Gateway 一致)
- *
- * @param memberId 会员 ID
- * @param tokenType Token 类型(access/refresh)
- * @return JWT Token 字符串
- */
- private String generateJwtToken(Long memberId, String tokenType) {
- return generateJwtToken(memberId, tokenType, jwtProperties.getExpiration());
- }
-
- /**
- * 生成 JWT Token(自定义过期时间)
- *
- * @param memberId 会员 ID
- * @param tokenType Token 类型(access/refresh)
- * @param expirationMs 过期时间(毫秒)
- * @return JWT Token 字符串
- */
- private String generateJwtToken(Long memberId, String tokenType, long expirationMs) {
- SecretKey key = Keys.hmacShaKeyFor(jwtProperties.getSecret().getBytes(StandardCharsets.UTF_8));
- Date now = new Date();
- Date expiryDate = new Date(now.getTime() + expirationMs);
-
- Map claims = new HashMap<>();
- claims.put("memberId", memberId);
- claims.put("tokenType", tokenType);
-
- return Jwts.builder()
- .setClaims(claims)
- .setSubject(String.valueOf(memberId))
- .setIssuedAt(now)
- .setExpiration(expiryDate)
- .signWith(key)
- .compact();
- }
}
diff --git a/gym-manage-api/gym-member/src/main/java/cn/novalon/gym/manage/member/util/AuthUtil.java b/gym-manage-api/gym-member/src/main/java/cn/novalon/gym/manage/member/util/AuthUtil.java
new file mode 100644
index 0000000..c2a9ea6
--- /dev/null
+++ b/gym-manage-api/gym-member/src/main/java/cn/novalon/gym/manage/member/util/AuthUtil.java
@@ -0,0 +1,32 @@
+package cn.novalon.gym.manage.member.util;
+
+import cn.novalon.gym.manage.sys.security.JwtTokenProvider;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.server.ResponseStatusException;
+
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class AuthUtil {
+
+ private final JwtTokenProvider jwtTokenProvider;
+
+ public String extractToken(ServerRequest request) {
+ String authorization = request.headers().firstHeader(HttpHeaders.AUTHORIZATION);
+ if (authorization == null || !authorization.startsWith("Bearer ")) return null;
+ return authorization.substring(7);
+ }
+
+ public Long getMemberIdOrThrow(ServerRequest request) {
+ String token = extractToken(request);
+ if (token == null) throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "缺少 Token");
+ if (!jwtTokenProvider.validateToken(token)) throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Token 无效或已过期");
+ if (jwtTokenProvider.getUserIdFromToken(token) <= 0L) throw new IllegalArgumentException("ID无效");
+ return jwtTokenProvider.getUserIdFromToken(token);
+ }
+}
\ No newline at end of file
diff --git a/gym-manage-api/manage-app/pom.xml b/gym-manage-api/manage-app/pom.xml
index ced508a..5eecb9d 100644
--- a/gym-manage-api/manage-app/pom.xml
+++ b/gym-manage-api/manage-app/pom.xml
@@ -43,6 +43,11 @@
gym-member
${project.version}
+
+ cn.novalon.gym.manage
+ gym-checkIn
+ ${project.version}
+
org.springframework.boot
spring-boot-starter-webflux
diff --git a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java
index 03ca331..4df2a4b 100644
--- a/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java
+++ b/gym-manage-api/manage-sys/src/main/java/cn/novalon/gym/manage/sys/config/SecurityConfig.java
@@ -50,8 +50,7 @@ public class SecurityConfig {
spec.pathMatchers("/api/auth/**").permitAll()
.pathMatchers("/api/public/**").permitAll()
.pathMatchers("/ws/**").permitAll()
- .pathMatchers("/actuator/**").permitAll()
- .pathMatchers("/api/member/checkIn").permitAll();
+ .pathMatchers("/actuator/**").permitAll();
if (isDevOrTest) {
spec.pathMatchers("/swagger-ui.html").permitAll()
diff --git a/gym-manage-api/pom.xml b/gym-manage-api/pom.xml
index 9681760..70df0c1 100644
--- a/gym-manage-api/pom.xml
+++ b/gym-manage-api/pom.xml
@@ -43,7 +43,8 @@
manage-notify
manage-file
gym-member
-
+ gym-checkIn
+