diff --git a/src/main/java/com/gxwebsoft/hjc/auth/HjcAuthResponses.java b/src/main/java/com/gxwebsoft/hjc/auth/HjcAuthResponses.java new file mode 100644 index 0000000..5400c5b --- /dev/null +++ b/src/main/java/com/gxwebsoft/hjc/auth/HjcAuthResponses.java @@ -0,0 +1,50 @@ +package com.gxwebsoft.hjc.auth; + +import com.gxwebsoft.common.core.Constants; +import com.gxwebsoft.common.core.web.ApiResult; + +/** + * 汇吉采买家接口的统一响应。 + * + *

为什么需要它:共享 {@code SecurityConfig} 里 {@code GET /**} 是放行的, + * 所以未登录的 GET 请求会**进到 controller**,由 controller 自己判登录态。 + * 此前这些地方返回的是 {@code fail("用户未登录")},即 {@code code=1}—— + * 与「业务失败」同一个码,前端无法据此判定登录失效。

+ * + *

约定(与平台既有常量一致,不新造码值):

+ * + * + *

复用 {@link Constants#UNAUTHENTICATED_CODE} 与 {@link Constants#UNAUTHENTICATED_MSG}: + * 这两个常量本就为此准备,此前唯一引用处是被注释掉的代码。

+ */ +public final class HjcAuthResponses { + + private HjcAuthResponses() { + } + + /** + * 未登录 / 凭据失效:{@code code=401, message="请先登录"}。 + * + *

用于 controller 内自行判定登录态的场景(GET 放行时不会经过安全过滤器)。

+ */ + public static ApiResult unauthorized() { + return new ApiResult<>(Constants.UNAUTHENTICATED_CODE, Constants.UNAUTHENTICATED_MSG); + } + + /** + * 已登录但无权访问该资源:{@code code=403}。 + * + *

与 {@code @PreAuthorize} 抛出的 {@code AccessDeniedException} 归为同一个码, + * 使前端只需记一套规则:401 清凭据跳登录、403 只提示。

+ * + * @param message 具体原因(例如「无权查看该订单」),直接展示给用户 + */ + public static ApiResult forbidden(String message) { + return new ApiResult<>(Constants.UNAUTHORIZED_CODE, + message == null ? Constants.UNAUTHORIZED_MSG : message); + } +} diff --git a/src/main/java/com/gxwebsoft/hjc/controller/HjcEnterpriseController.java b/src/main/java/com/gxwebsoft/hjc/controller/HjcEnterpriseController.java index 6f31114..39d15fc 100644 --- a/src/main/java/com/gxwebsoft/hjc/controller/HjcEnterpriseController.java +++ b/src/main/java/com/gxwebsoft/hjc/controller/HjcEnterpriseController.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.core.web.PageResult; +import com.gxwebsoft.hjc.auth.HjcAuthResponses; import com.gxwebsoft.hjc.entity.HjcEnterprise; import com.gxwebsoft.hjc.entity.HjcEnterpriseMaterial; import com.gxwebsoft.hjc.param.HjcEnterpriseParam; @@ -37,7 +38,7 @@ public class HjcEnterpriseController extends BaseController { public ApiResult my() { Integer userId = getLoginUserId(); if (userId == null) { - return fail("用户未登录"); + return HjcAuthResponses.unauthorized(); } HjcEnterprise enterprise = hjcEnterpriseService.getByUserId(userId); if (enterprise != null) { @@ -53,7 +54,7 @@ public class HjcEnterpriseController extends BaseController { public ApiResult save(@RequestBody HjcEnterprise enterprise) { Integer userId = getLoginUserId(); if (userId == null) { - return fail("用户未登录"); + return HjcAuthResponses.unauthorized(); } HjcEnterprise exist = hjcEnterpriseService.getByUserId(userId); boolean isNew = exist == null; diff --git a/src/main/java/com/gxwebsoft/hjc/controller/HjcOrderController.java b/src/main/java/com/gxwebsoft/hjc/controller/HjcOrderController.java index 9caf49a..9f67cdd 100644 --- a/src/main/java/com/gxwebsoft/hjc/controller/HjcOrderController.java +++ b/src/main/java/com/gxwebsoft/hjc/controller/HjcOrderController.java @@ -8,6 +8,7 @@ import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.hjc.dto.CreateOrderRequest; import com.gxwebsoft.hjc.auth.HjcAdminGuard; import com.gxwebsoft.common.system.entity.User; +import com.gxwebsoft.hjc.auth.HjcAuthResponses; import com.gxwebsoft.hjc.entity.HjcBidProject; import com.gxwebsoft.hjc.entity.HjcEnterprise; import com.gxwebsoft.hjc.entity.HjcOrder; @@ -60,7 +61,7 @@ public class HjcOrderController extends BaseController { public ApiResult create(@RequestBody CreateOrderRequest request) { Integer userId = getLoginUserId(); if (userId == null) { - return fail("用户未登录"); + return HjcAuthResponses.unauthorized(); } HjcEnterprise enterprise = hjcEnterpriseService.getByUserId(userId); if (enterprise == null) { @@ -119,7 +120,7 @@ public class HjcOrderController extends BaseController { public ApiResult pay(@RequestBody Map body) { Integer userId = getLoginUserId(); if (userId == null) { - return fail("用户未登录"); + return HjcAuthResponses.unauthorized(); } String orderNo = body.get("orderNo") == null ? null : String.valueOf(body.get("orderNo")); if (orderNo == null) { @@ -159,7 +160,7 @@ public class HjcOrderController extends BaseController { public ApiResult markPaid(@RequestBody Map body) { Integer userId = getLoginUserId(); if (userId == null) { - return fail("用户未登录"); + return HjcAuthResponses.unauthorized(); } String orderNo = body.get("orderNo") == null ? null : String.valueOf(body.get("orderNo")); if (orderNo == null) { @@ -181,7 +182,7 @@ public class HjcOrderController extends BaseController { public ApiResult my() { Integer userId = getLoginUserId(); if (userId == null) { - return fail("用户未登录"); + return HjcAuthResponses.unauthorized(); } HjcEnterprise enterprise = hjcEnterpriseService.getByUserId(userId); if (enterprise == null) { @@ -200,7 +201,7 @@ public class HjcOrderController extends BaseController { // 枚举出哪些订单 ID 真实存在。 User loginUser = hjcGuard.currentUser(); if (loginUser == null) { - return fail("用户未登录"); + return HjcAuthResponses.unauthorized(); } HjcOrder order = hjcOrderService.getById(id); if (order == null) { @@ -211,7 +212,7 @@ public class HjcOrderController extends BaseController { if (!hjcGuard.isAdmin()) { HjcEnterprise enterprise = hjcEnterpriseService.getByUserId(loginUser.getUserId()); if (enterprise == null || !enterprise.getId().equals(order.getEnterpriseId())) { - return fail("无权查看该订单"); + return HjcAuthResponses.forbidden("无权查看该订单"); } } order.setProject(hjcBidProjectService.getById(order.getProjectId())); diff --git a/src/test/java/com/gxwebsoft/hjc/auth/HjcAuthResponsesTest.java b/src/test/java/com/gxwebsoft/hjc/auth/HjcAuthResponsesTest.java new file mode 100644 index 0000000..64aedf5 --- /dev/null +++ b/src/test/java/com/gxwebsoft/hjc/auth/HjcAuthResponsesTest.java @@ -0,0 +1,39 @@ +package com.gxwebsoft.hjc.auth; + +import com.gxwebsoft.common.core.Constants; +import com.gxwebsoft.common.core.web.ApiResult; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * 响应码契约:前端只认一套规则——401 清凭据跳登录、403 只提示。 + * + *

此前 hjc 买家接口在未登录时返回 {@code code=1}「用户未登录」,与业务失败同码, + * 前端无法据此判定登录失效(PC 端会把它显示成一句错误提示,而不是回登录页)。

+ */ +class HjcAuthResponsesTest { + + @Test + void 未登录必须是401而不是1() { + ApiResult r = HjcAuthResponses.unauthorized(); + assertEquals(401, r.getCode().intValue(), "未登录必须是 401,否则前端无法判定登录失效"); + } + + @Test + void 未登录文案用平台既有常量() { + assertEquals(Constants.UNAUTHENTICATED_MSG, HjcAuthResponses.unauthorized().getMessage()); + } + + @Test + void 越权必须是403且保留具体原因() { + ApiResult r = HjcAuthResponses.forbidden("无权查看该订单"); + assertEquals(403, r.getCode().intValue(), "已登录但越权必须是 403(与 @PreAuthorize 同码)"); + assertEquals("无权查看该订单", r.getMessage()); + } + + @Test + void 越权未给原因时用平台默认文案() { + assertEquals(Constants.UNAUTHORIZED_MSG, HjcAuthResponses.forbidden(null).getMessage()); + } +}