diff --git a/src/main/java/com/aida/buyer/module/account/controller/BuyerAccountController.java b/src/main/java/com/aida/buyer/module/account/controller/BuyerAccountController.java index d8d49d0..d65ed67 100644 --- a/src/main/java/com/aida/buyer/module/account/controller/BuyerAccountController.java +++ b/src/main/java/com/aida/buyer/module/account/controller/BuyerAccountController.java @@ -1,5 +1,6 @@ package com.aida.buyer.module.account.controller; +import com.aida.buyer.common.context.UserContext; import com.aida.buyer.common.result.Response; import com.aida.buyer.module.account.dto.*; import com.aida.buyer.module.account.service.IBuyerAccountService; @@ -67,4 +68,10 @@ public class BuyerAccountController { public Response bindEmail(@Valid @RequestBody BindEmailDTO dto) { return buyerAccountService.bindEmail(dto); } + + @PostMapping("/logout") + @Operation(summary = "登出:清除本地 token 并将用户加入 gateway 黑名单") + public Response logout(@RequestBody LogoutDTO dto) { + return buyerAccountService.logout(dto.getUserId()); + } } diff --git a/src/main/java/com/aida/buyer/module/account/dto/LogoutDTO.java b/src/main/java/com/aida/buyer/module/account/dto/LogoutDTO.java new file mode 100644 index 0000000..f504aa6 --- /dev/null +++ b/src/main/java/com/aida/buyer/module/account/dto/LogoutDTO.java @@ -0,0 +1,14 @@ +package com.aida.buyer.module.account.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Data +@Schema(description = "登出请求") +public class LogoutDTO { + + @NotNull(message = "userId is required") + @Schema(description = "用户ID") + private Long userId; +} diff --git a/src/main/java/com/aida/buyer/module/account/feign/GatewayFeignClient.java b/src/main/java/com/aida/buyer/module/account/feign/GatewayFeignClient.java new file mode 100644 index 0000000..86bae96 --- /dev/null +++ b/src/main/java/com/aida/buyer/module/account/feign/GatewayFeignClient.java @@ -0,0 +1,20 @@ +package com.aida.buyer.module.account.feign; + +import com.aida.buyer.common.result.Response; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; + +/** + * 调用 Gateway 黑名单接口,将指定用户的 token 加入黑名单。 + */ +@FeignClient(name = "aida-gateway", path = "/internal") +public interface GatewayFeignClient { + + /** + * 将用户 token 加入黑名单。 + * Gateway 会拒绝携带该用户 token 的后续请求。 + */ + @PostMapping("/logout") + Response logout(@RequestParam("userId") Long userId); +} diff --git a/src/main/java/com/aida/buyer/module/account/service/IBuyerAccountService.java b/src/main/java/com/aida/buyer/module/account/service/IBuyerAccountService.java index 58b0763..f86a732 100644 --- a/src/main/java/com/aida/buyer/module/account/service/IBuyerAccountService.java +++ b/src/main/java/com/aida/buyer/module/account/service/IBuyerAccountService.java @@ -21,4 +21,6 @@ public interface IBuyerAccountService { Response sendEmailChangeCode(SendEmailCodeDTO dto); Response bindEmail(BindEmailDTO dto); + + Response logout(Long userId); } diff --git a/src/main/java/com/aida/buyer/module/account/service/impl/BuyerAccountServiceImpl.java b/src/main/java/com/aida/buyer/module/account/service/impl/BuyerAccountServiceImpl.java index 523cac0..568e195 100644 --- a/src/main/java/com/aida/buyer/module/account/service/impl/BuyerAccountServiceImpl.java +++ b/src/main/java/com/aida/buyer/module/account/service/impl/BuyerAccountServiceImpl.java @@ -6,6 +6,7 @@ import com.aida.buyer.common.exception.BusinessException; import com.aida.buyer.model.vo.AuthPrincipalVo; import com.aida.buyer.module.account.entity.BuyerAccount; import com.aida.buyer.module.account.mapper.BuyerAccountMapper; +import com.aida.buyer.module.account.feign.GatewayFeignClient; import com.aida.buyer.module.account.service.IBuyerAccountService; import com.aida.buyer.util.LoginCacheUtil; import com.aida.buyer.util.RandomsUtil; @@ -26,6 +27,7 @@ public class BuyerAccountServiceImpl implements IBuyerAccountService { private final BuyerAccountMapper buyerAccountMapper; private final TokenGenerateUtils tokenGenerateUtils; private final RedisLoginUtil redisLoginUtil; + private final GatewayFeignClient gatewayFeignClient; @Override public Response sendCode(SendCodeDTO dto) { @@ -274,4 +276,16 @@ public class BuyerAccountServiceImpl implements IBuyerAccountService { return Response.success(new BindEmailVO(account.getId(), newEmail)); } + + @Override + public Response logout(Long userId) { + redisLoginUtil.deleteLoginToken(userId); + try { + gatewayFeignClient.logout(userId); + } catch (Exception e) { + log.warn("Failed to add token to gateway blacklist, userId={}, error={}", userId, e.getMessage()); + } + log.info("Buyer logged out, userId={}", userId); + return Response.success(Boolean.TRUE); + } } diff --git a/src/main/java/com/aida/buyer/module/cart/dto/CartItemDTO.java b/src/main/java/com/aida/buyer/module/cart/dto/CartItemDTO.java index d1f9174..a5d8e74 100644 --- a/src/main/java/com/aida/buyer/module/cart/dto/CartItemDTO.java +++ b/src/main/java/com/aida/buyer/module/cart/dto/CartItemDTO.java @@ -41,4 +41,7 @@ public class CartItemDTO implements Serializable { @Schema(description = "加入购物车时间") private LocalDateTime addTime; + + /** 店铺名称 */ + private String shopName; } diff --git a/src/main/java/com/aida/buyer/module/cart/service/impl/CartServiceImpl.java b/src/main/java/com/aida/buyer/module/cart/service/impl/CartServiceImpl.java index 95322f6..0ddee3b 100644 --- a/src/main/java/com/aida/buyer/module/cart/service/impl/CartServiceImpl.java +++ b/src/main/java/com/aida/buyer/module/cart/service/impl/CartServiceImpl.java @@ -102,6 +102,7 @@ public class CartServiceImpl implements ICartService { dto.setStatus(listing.getStatus()); dto.setProductCategory(listing.getProductCategory()); dto.setAddTime(item.getAddTime()); + dto.setShopName(listing.getShopName()); return dto; }) .toList(); diff --git a/src/main/java/com/aida/buyer/module/listing/vo/ListingMallVO.java b/src/main/java/com/aida/buyer/module/listing/vo/ListingMallVO.java index 790d2d0..edd38de 100644 --- a/src/main/java/com/aida/buyer/module/listing/vo/ListingMallVO.java +++ b/src/main/java/com/aida/buyer/module/listing/vo/ListingMallVO.java @@ -29,4 +29,7 @@ public class ListingMallVO implements Serializable { /** 商品分类列表 */ private List productCategory; + + /** 店铺名称 */ + private String shopName; }