电商项目收货地址模块在开发中如何解决横向越权安全问题

什么是横向越权/纵向越权?

横向越权:横向越权指的是攻击者尝试访问与他拥有相同权限的用户的资源。
纵向越权:纵向越权指的是一个低级别攻击者尝试访问高级别用户的资源。

如何防止横向越权漏洞?

       可通过建立用户和可操作资源的绑定关系,用户对任何资源进行操作时,通过该绑定关系确保该资源是属于该用户所有的。对请求中的关键参数进行间接映射,避免使用原始关键参数名,比如使用索引1代替id值123等

如何防止纵向越权漏洞?

        建议使用基于角色访问控制机制来防止纵向越权攻击,即预先定义不同的权限角色,为每个角色分配不同的权限,每个用户都属于特定的角色,即拥有固定的权限,当用户执行某个动作或产生某种行为时,通过用户所在的角色判定该动作或者行为是否允许。

功能场景

电商项目在收货地址模块中存在添加地址、删除地址、修改地址、更新地址等等功能实现,在实现地址的删除/更新/查询功能的时候,会存在横向越权的安全隐患,在登陆的时候,我们用户都是登录的普通用户账号,防止有些黑客或者不法分子在登陆以后,传一个不是自己的shippingId,那么他就可以随意的篡改我们的信息,使得信息泄露等隐患,比如:

ShippingServiceImpl.java

   public ServerResponse<String> delete(Integer userId, Integer shippingId) {
        //直接调用Mybatis的deleteByPrimaryKey()方法
        int rowCount = shippingMapper.deleteByPrimaryKey(shippingId);
        if (rowCount > 0) {
            return ServerResponse.createBySuccessMessage("删除地址成功");
        }
        return ServerResponse.createByErrorMessage("删除地址失败");
    }

在删除收货地址功能实现的时,倘若我们直接使用deleteByPrimaryKey()来删除地址,就会存在横向越权的隐患,应为黑客他同样能调用该接口来删除,那么那么为了解决这类问题,我们必须自定义一个新的删除方法来跟我们登陆用户的可操作资源进行绑定起来从而实现对地址的删除:

 @Override
    public ServerResponse<String> delete(Integer userId, Integer shippingId) {
        //为了防止横向越权这个方法不可以使用,不需要定义deleteByUserIdShippingId()方法来实现删除
//        int rowCount = shippingMapper.deleteByPrimaryKey(shippingId);
        int rowCount = shippingMapper.deleteByUserIdShippingId(userId, shippingId);
        if (rowCount > 0) {
            return ServerResponse.createBySuccessMessage("删除地址成功");
        }
        return ServerResponse.createByErrorMessage("删除地址失败");
    }

这时候,删除地址需要传一个userId的参数,因此能避免不法分子直接进行删除操作!dao层的方法如下:

int deleteByUserIdShippingId(@Param("userId")Integer userId,@Param("shippingId") Integer shippingId);

实现地址的更新功能的时候同样会存在横向越权的安全隐患:

 @Override
    public ServerResponse update(Integer userId, Shipping shipping) {
        //重新赋值userId
        shipping.setUserId(userId);
        /**
         * 使用登陆的shipping重新赋值给userId,为什么还需要重新赋值一下???因为shipping的userId也是可以模拟的,
         * 如果不从登陆用户里面拿,直接用传来的userId,这样也会把被人的地址更新掉,那么还是存在越权问题的,所有要重新赋值一下。
         */
        int rowCount = shippingMapper.updateByShipping(shipping);
        if (rowCount > 0) {
            return ServerResponse.createBySuccessMessage("更新地址信息成功");
        }
        return ServerResponse.createByErrorMessage("更新地址信息失败");
    }

这里为什么要重新赋值userId呢?因为shipping的userId也是可以模拟的, 如果不从登陆用户里面拿,直接用传来的userId,这样也会把被人的地址更新掉,那么还是存在越权问题的,所有要重新赋值一下。

同样也需要我们重新定义一个更新方法,为了让用户的可操作资源跟用户绑定起来,方法如下:

ShippingMapper和ShippingMapper.xml

int updateByShipping(Shipping shipping);
<update id="updateByShipping" parameterType="com.lbz.entity.Shipping">
   update tb_shipping
   set
      receiver_name = #{receiverName,jdbcType=VARCHAR},
      receiver_phone = #{receiverPhone,jdbcType=VARCHAR},
      receiver_province = #{receiverProvince,jdbcType=VARCHAR},
      receiver_city = #{receiverCity,jdbcType=VARCHAR},
      receiver_district = #{receiverDistrict,jdbcType=VARCHAR},
      receiver_address = #{receiverAddress,jdbcType=VARCHAR},
      zip_code = #{zipCode,jdbcType=VARCHAR},
      create_time = #{createTime,jdbcType=TIMESTAMP},
      update_time = now()
      where id = #{id,jdbcType=INTEGER}

      --指定user_id为当前用户的id       
      and user_id = #{userId,jdbcType=INTEGER}
</update>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值