fix(hjc): 买家接口未登录统一返回 401,越权返回 403(此前与业务失败同为 code=1)
共享 SecurityConfig 里 GET /** 放行,未登录的 GET 会进到 controller 由 controller
自行判登录态;此前这些地方返回 fail("用户未登录") 即 code=1,与业务失败同码,
前端无法据此判定登录失效——PC 端会把它显示成一句错误提示,而不是清凭据回登录页。
- 新增 HjcAuthResponses:unauthorized() → 401「请先登录」,
forbidden(msg) → 403;复用平台既有常量 Constants.UNAUTHENTICATED_CODE/_MSG
(这两个常量本就为此准备,此前唯一引用处是被注释掉的代码),不新造码值
- 7 处未登录返回改为 401:enterprise/my、enterprise/save、
order/create、order/pay、order/mark-paid、order/my、order/{id}
- 订单详情的「无权查看该订单」改为 403,与 @PreAuthorize 的 AccessDeniedException
归为同一个码,前端只需记一套规则(401 清凭据跳登录、403 只提示)
- 新增 HjcAuthResponsesTest 锁定契约(实测把码值改回 1 则测试红)
- 未改动共享 BaseController 与 SecurityConfig,改动面限于 hjc 包
This commit is contained in:
@@ -0,0 +1,50 @@
|
|||||||
|
package com.gxwebsoft.hjc.auth;
|
||||||
|
|
||||||
|
import com.gxwebsoft.common.core.Constants;
|
||||||
|
import com.gxwebsoft.common.core.web.ApiResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 汇吉采买家接口的统一响应。
|
||||||
|
*
|
||||||
|
* <p><b>为什么需要它</b>:共享 {@code SecurityConfig} 里 {@code GET /**} 是放行的,
|
||||||
|
* 所以未登录的 GET 请求会**进到 controller**,由 controller 自己判登录态。
|
||||||
|
* 此前这些地方返回的是 {@code fail("用户未登录")},即 {@code code=1}——
|
||||||
|
* 与「业务失败」同一个码,前端无法据此判定登录失效。</p>
|
||||||
|
*
|
||||||
|
* <p>约定(与平台既有常量一致,不新造码值):</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code 401} = 未登录 / 凭据失效 → 前端应清凭据并跳登录页</li>
|
||||||
|
* <li>{@code 403} = 已登录但无权限(由 {@code @PreAuthorize} 抛
|
||||||
|
* {@code AccessDeniedException} 产生)→ 前端只提示,不清凭据</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>复用 {@link Constants#UNAUTHENTICATED_CODE} 与 {@link Constants#UNAUTHENTICATED_MSG}:
|
||||||
|
* 这两个常量本就为此准备,此前唯一引用处是被注释掉的代码。</p>
|
||||||
|
*/
|
||||||
|
public final class HjcAuthResponses {
|
||||||
|
|
||||||
|
private HjcAuthResponses() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 未登录 / 凭据失效:{@code code=401, message="请先登录"}。
|
||||||
|
*
|
||||||
|
* <p>用于 controller 内自行判定登录态的场景(GET 放行时不会经过安全过滤器)。</p>
|
||||||
|
*/
|
||||||
|
public static <T> ApiResult<T> unauthorized() {
|
||||||
|
return new ApiResult<>(Constants.UNAUTHENTICATED_CODE, Constants.UNAUTHENTICATED_MSG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已登录但无权访问该资源:{@code code=403}。
|
||||||
|
*
|
||||||
|
* <p>与 {@code @PreAuthorize} 抛出的 {@code AccessDeniedException} 归为同一个码,
|
||||||
|
* 使前端只需记一套规则:401 清凭据跳登录、403 只提示。</p>
|
||||||
|
*
|
||||||
|
* @param message 具体原因(例如「无权查看该订单」),直接展示给用户
|
||||||
|
*/
|
||||||
|
public static <T> ApiResult<T> forbidden(String message) {
|
||||||
|
return new ApiResult<>(Constants.UNAUTHORIZED_CODE,
|
||||||
|
message == null ? Constants.UNAUTHORIZED_MSG : message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.ApiResult;
|
||||||
import com.gxwebsoft.common.core.web.BaseController;
|
import com.gxwebsoft.common.core.web.BaseController;
|
||||||
import com.gxwebsoft.common.core.web.PageResult;
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import com.gxwebsoft.hjc.auth.HjcAuthResponses;
|
||||||
import com.gxwebsoft.hjc.entity.HjcEnterprise;
|
import com.gxwebsoft.hjc.entity.HjcEnterprise;
|
||||||
import com.gxwebsoft.hjc.entity.HjcEnterpriseMaterial;
|
import com.gxwebsoft.hjc.entity.HjcEnterpriseMaterial;
|
||||||
import com.gxwebsoft.hjc.param.HjcEnterpriseParam;
|
import com.gxwebsoft.hjc.param.HjcEnterpriseParam;
|
||||||
@@ -37,7 +38,7 @@ public class HjcEnterpriseController extends BaseController {
|
|||||||
public ApiResult<?> my() {
|
public ApiResult<?> my() {
|
||||||
Integer userId = getLoginUserId();
|
Integer userId = getLoginUserId();
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
return fail("用户未登录");
|
return HjcAuthResponses.unauthorized();
|
||||||
}
|
}
|
||||||
HjcEnterprise enterprise = hjcEnterpriseService.getByUserId(userId);
|
HjcEnterprise enterprise = hjcEnterpriseService.getByUserId(userId);
|
||||||
if (enterprise != null) {
|
if (enterprise != null) {
|
||||||
@@ -53,7 +54,7 @@ public class HjcEnterpriseController extends BaseController {
|
|||||||
public ApiResult<?> save(@RequestBody HjcEnterprise enterprise) {
|
public ApiResult<?> save(@RequestBody HjcEnterprise enterprise) {
|
||||||
Integer userId = getLoginUserId();
|
Integer userId = getLoginUserId();
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
return fail("用户未登录");
|
return HjcAuthResponses.unauthorized();
|
||||||
}
|
}
|
||||||
HjcEnterprise exist = hjcEnterpriseService.getByUserId(userId);
|
HjcEnterprise exist = hjcEnterpriseService.getByUserId(userId);
|
||||||
boolean isNew = exist == null;
|
boolean isNew = exist == null;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.gxwebsoft.common.core.web.PageResult;
|
|||||||
import com.gxwebsoft.hjc.dto.CreateOrderRequest;
|
import com.gxwebsoft.hjc.dto.CreateOrderRequest;
|
||||||
import com.gxwebsoft.hjc.auth.HjcAdminGuard;
|
import com.gxwebsoft.hjc.auth.HjcAdminGuard;
|
||||||
import com.gxwebsoft.common.system.entity.User;
|
import com.gxwebsoft.common.system.entity.User;
|
||||||
|
import com.gxwebsoft.hjc.auth.HjcAuthResponses;
|
||||||
import com.gxwebsoft.hjc.entity.HjcBidProject;
|
import com.gxwebsoft.hjc.entity.HjcBidProject;
|
||||||
import com.gxwebsoft.hjc.entity.HjcEnterprise;
|
import com.gxwebsoft.hjc.entity.HjcEnterprise;
|
||||||
import com.gxwebsoft.hjc.entity.HjcOrder;
|
import com.gxwebsoft.hjc.entity.HjcOrder;
|
||||||
@@ -60,7 +61,7 @@ public class HjcOrderController extends BaseController {
|
|||||||
public ApiResult<?> create(@RequestBody CreateOrderRequest request) {
|
public ApiResult<?> create(@RequestBody CreateOrderRequest request) {
|
||||||
Integer userId = getLoginUserId();
|
Integer userId = getLoginUserId();
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
return fail("用户未登录");
|
return HjcAuthResponses.unauthorized();
|
||||||
}
|
}
|
||||||
HjcEnterprise enterprise = hjcEnterpriseService.getByUserId(userId);
|
HjcEnterprise enterprise = hjcEnterpriseService.getByUserId(userId);
|
||||||
if (enterprise == null) {
|
if (enterprise == null) {
|
||||||
@@ -119,7 +120,7 @@ public class HjcOrderController extends BaseController {
|
|||||||
public ApiResult<?> pay(@RequestBody Map<String, Object> body) {
|
public ApiResult<?> pay(@RequestBody Map<String, Object> body) {
|
||||||
Integer userId = getLoginUserId();
|
Integer userId = getLoginUserId();
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
return fail("用户未登录");
|
return HjcAuthResponses.unauthorized();
|
||||||
}
|
}
|
||||||
String orderNo = body.get("orderNo") == null ? null : String.valueOf(body.get("orderNo"));
|
String orderNo = body.get("orderNo") == null ? null : String.valueOf(body.get("orderNo"));
|
||||||
if (orderNo == null) {
|
if (orderNo == null) {
|
||||||
@@ -159,7 +160,7 @@ public class HjcOrderController extends BaseController {
|
|||||||
public ApiResult<?> markPaid(@RequestBody Map<String, Object> body) {
|
public ApiResult<?> markPaid(@RequestBody Map<String, Object> body) {
|
||||||
Integer userId = getLoginUserId();
|
Integer userId = getLoginUserId();
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
return fail("用户未登录");
|
return HjcAuthResponses.unauthorized();
|
||||||
}
|
}
|
||||||
String orderNo = body.get("orderNo") == null ? null : String.valueOf(body.get("orderNo"));
|
String orderNo = body.get("orderNo") == null ? null : String.valueOf(body.get("orderNo"));
|
||||||
if (orderNo == null) {
|
if (orderNo == null) {
|
||||||
@@ -181,7 +182,7 @@ public class HjcOrderController extends BaseController {
|
|||||||
public ApiResult<?> my() {
|
public ApiResult<?> my() {
|
||||||
Integer userId = getLoginUserId();
|
Integer userId = getLoginUserId();
|
||||||
if (userId == null) {
|
if (userId == null) {
|
||||||
return fail("用户未登录");
|
return HjcAuthResponses.unauthorized();
|
||||||
}
|
}
|
||||||
HjcEnterprise enterprise = hjcEnterpriseService.getByUserId(userId);
|
HjcEnterprise enterprise = hjcEnterpriseService.getByUserId(userId);
|
||||||
if (enterprise == null) {
|
if (enterprise == null) {
|
||||||
@@ -200,7 +201,7 @@ public class HjcOrderController extends BaseController {
|
|||||||
// 枚举出哪些订单 ID 真实存在。
|
// 枚举出哪些订单 ID 真实存在。
|
||||||
User loginUser = hjcGuard.currentUser();
|
User loginUser = hjcGuard.currentUser();
|
||||||
if (loginUser == null) {
|
if (loginUser == null) {
|
||||||
return fail("用户未登录");
|
return HjcAuthResponses.unauthorized();
|
||||||
}
|
}
|
||||||
HjcOrder order = hjcOrderService.getById(id);
|
HjcOrder order = hjcOrderService.getById(id);
|
||||||
if (order == null) {
|
if (order == null) {
|
||||||
@@ -211,7 +212,7 @@ public class HjcOrderController extends BaseController {
|
|||||||
if (!hjcGuard.isAdmin()) {
|
if (!hjcGuard.isAdmin()) {
|
||||||
HjcEnterprise enterprise = hjcEnterpriseService.getByUserId(loginUser.getUserId());
|
HjcEnterprise enterprise = hjcEnterpriseService.getByUserId(loginUser.getUserId());
|
||||||
if (enterprise == null || !enterprise.getId().equals(order.getEnterpriseId())) {
|
if (enterprise == null || !enterprise.getId().equals(order.getEnterpriseId())) {
|
||||||
return fail("无权查看该订单");
|
return HjcAuthResponses.forbidden("无权查看该订单");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
order.setProject(hjcBidProjectService.getById(order.getProjectId()));
|
order.setProject(hjcBidProjectService.getById(order.getProjectId()));
|
||||||
|
|||||||
@@ -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 只提示。
|
||||||
|
*
|
||||||
|
* <p>此前 hjc 买家接口在未登录时返回 {@code code=1}「用户未登录」,与业务失败同码,
|
||||||
|
* 前端无法据此判定登录失效(PC 端会把它显示成一句错误提示,而不是回登录页)。</p>
|
||||||
|
*/
|
||||||
|
class HjcAuthResponsesTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 未登录必须是401而不是1() {
|
||||||
|
ApiResult<Object> r = HjcAuthResponses.unauthorized();
|
||||||
|
assertEquals(401, r.getCode().intValue(), "未登录必须是 401,否则前端无法判定登录失效");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 未登录文案用平台既有常量() {
|
||||||
|
assertEquals(Constants.UNAUTHENTICATED_MSG, HjcAuthResponses.unauthorized().getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 越权必须是403且保留具体原因() {
|
||||||
|
ApiResult<Object> r = HjcAuthResponses.forbidden("无权查看该订单");
|
||||||
|
assertEquals(403, r.getCode().intValue(), "已登录但越权必须是 403(与 @PreAuthorize 同码)");
|
||||||
|
assertEquals("无权查看该订单", r.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void 越权未给原因时用平台默认文案() {
|
||||||
|
assertEquals(Constants.UNAUTHORIZED_MSG, HjcAuthResponses.forbidden(null).getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user