找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4656

积分

0

好友

608

主题
发表于 3 小时前 | 查看: 5| 回复: 0

有网友吐槽,业务负责人娶小老婆,居然要求下面员工随份子。不交的人被暗示“不懂事”,交了的人也觉得憋屈。

这种事情表面看是职场人情,实际上暴露的是一个更危险的问题:权力没有边界。

网友吐槽业务负责人娶小老婆让员工随份子钱

技术团队里也一样。很多线上事故不是代码写错,而是某个人权限太大、某个服务职责太乱,最后所有人都被迫为一个错误买单。

比如一个业务负责人既能改订单规则,又能直接操作数据库,还能绕过审批发布代码。平时看起来效率很高,出问题时就是灾难。

今天聊一个真实开发中经常出现的问题:为什么权限越集中,系统越容易失控,以及 Java 系统 如何设计权限隔离。

一个接口上线后,订单金额被改了

生产环境出现异常:

09:12:31 订单服务报警
payment_amount异常增长

09:13:02 数据库监控
order_detail表 update QPS 突增

09:15:44 开发群:
“谁改了订单金额字段?”

查数据库:

select
id,
    order_no,
    payment_amount,
    update_user,
    update_time
from order_detail
where update_time > '2026-08-22 09:00:00';

结果:

id       order_no       payment_amount   update_user
10021    A20260822001   1999             admin
10022    A20260822002   2999             admin
10023    A20260822003   4999             admin

继续查操作日志:

operator=admin
action=UPDATE_ORDER
source=后台管理系统

问题很快定位:后台系统给了一个超级管理员接口:

@PostMapping("/order/update")
public Result update(@RequestBody OrderDTO dto){
    orderService.update(dto);
    return Result.success();
}

代码没报错,权限也通过了,但设计本身有问题。

因为这个接口实际上允许:改金额、改状态、改商品、改用户信息。一个入口控制全部业务。这就是典型的“大老板权限模型”,所有事情都归一个人管。

权限不是越大越方便,而是风险集中

很多系统早期都会这么设计:

if(user.isAdmin()){
    return true;
}

简单,开发快。但是半年后:运营需要改库存,客服需要补订单,财务需要退款。最后所有人都申请 admin。

权限表变成:

user_id   role
1001      admin
1002      admin
1003      admin
1004      admin

所谓权限控制,只剩一个按钮。

线上真正需要的是:角色控制资源,资源控制动作。

用户
 |
角色
 |
权限
 |
接口
 |
业务动作

数据库设计:

create table sys_permission(
id bigint primary key,
    code varchar(64),
    name varchar(128)
);

create table sys_role_permission(
    role_id bigint,
    permission_id bigint
);

权限不要只定义一个 UPDATE_ORDER,太粗了。应该拆成:

ORDER_VIEW
ORDER_CANCEL
ORDER_REFUND
ORDER_PRICE_EDIT

因为风险完全不同。查看订单:客服可以。修改价格:运营经理可以。退款:财务可以。这才是正常系统。

高风险操作必须二次确认

很多公司有权限,但是没有控制风险。例如退款:

public void refund(Long orderId){
    orderService.refund(orderId);
}

如果只判断有没有退款权限,远远不够。线上环境还应该增加:金额限制、审批、操作记录、双人确认。

例如:

public void refund(RefundCommand command){
    checkPermission();
    if(command.getAmount()
        .compareTo(new BigDecimal("5000")) > 0){
        throw new BizException("large refund require approval");
    }
    saveAuditLog(command);
    refundService.execute(command);
}

超过5000进入审批。不是因为技术复杂,而是因为错误成本高。

数据库权限也不能给开发“一把钥匙”

很多团队还有个习惯:开发拿着 root 账号直连生产库,图个排查方便。然后某天:

update user_account
set status=0;

忘记 where。几十万用户被冻结。

数据库层 应该拆账号:

读:app_read
写:app_write
发布:deploy_user
管理员:dba_user

例如 MySQL:

create user 'order_app'
identified by 'xxxx';

grant select, insert, update
on trade.*
to 'order_app';

不要:

grant all privileges
on *.*
to 'app';

这个权限看起来省事,实际上是在给未来事故留入口。

服务之间也需要边界

微服务 架构里也经常乱套:订单服务直接调用户库,库存服务直接改订单表。最后演变成:

订单服务
 |
 |
用户表
 |
 |
库存表

谁都能改,出了问题没人知道责任。更合理的方式是:

order-service
只负责:订单状态

inventory-service
只负责:库存扣减

payment-service
只负责:支付结果

调用流程:

createOrder
    |
    |
payment.pay()
    |
    |
inventory.lock()

而不是:

orderService.updateInventory();
orderService.updatePayment();
orderService.updateUser();

一个类知道太多事情,和一个人拥有太多权力,本质问题类似。边界消失,风险就会扩散。

线上排查时,我最先看权限链

遇到异常操作,我不会一上来就看代码,而是先看:

谁操作
↓
通过什么入口
↓
拥有哪个权限
↓
调用哪个服务
↓
修改什么数据

日志至少要记录:

{
"operator": "zhangsan",
"role": "finance_manager",
"action": "REFUND",
"resource": "order_10021",
"ip": "10.20.1.15",
"traceId": "abc123"
}

没有审计日志的问题,出了事故只能猜。猜一次没事,长期靠猜,系统一定会出问题。

这也是云栈社区上大家经常讨论的话题。职场里,没人应该为一个人的私人决定被迫买单;技术系统里,也不能让整个系统为一个超级权限设计买单。权限边界做好了,很多事故根本就不会发生。




上一篇:Fable 5.1全网实测:ARC跑分90%、成本降32%,写作终于像真人了
下一篇:Oracle 19c 自动索引新创建后是什么状态?可见性机制解析
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-9-6 07:05 , Processed in 1.071614 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表