PHP json函数遇到的字符编码问题

参考

json_decode produces error “Single unpaired UTF-16 surrogate in unicode escape” and returns null

PHP json_decode does not work with single unpaired surrogate caused by Node 12 well-formed JSON.stringify

php json函数只能支持utf-8编码

在调取其它语言接口时,json_decode报错Single unpaired UTF-16 surrogate in unicode escape

解决方法一

正则替换掉无效\u开头的unicode字符,然后json_decode

 $contents = preg_replace('/(?<!\\\)\\\u[a-f0-9]{4}/iu', '', $contents);
 $json = json_decode($contents, true);

解决方法二

自定义json_decode方法

 public function customJsonDecode($json)
    {
        $comment = false;
        $out = '$x=';

        for ($i = 0; $i < strlen($json); $i++)
        {
            if (!$comment)
            {
                if (($json[$i] == '{') || ($json[$i] == '[')) $out .= ' array(';
                else if (($json[$i] == '}') || ($json[$i] == ']')) $out .= ')';
                else if ($json[$i] == ':') $out .= '=>';
                else
                    $out .= $json[$i];
            }
            else
                $out .= $json[$i];
            if ($json[$i] == '"' && $json[($i - 1)] != "\\")
                $comment = !$comment;
        }

        eval($out . ';');

        return $x;
    }

网络安全 渗透测试 知识汇总

常见攻击方式和漏洞

DDOS 和 CC 攻击

什么是 DDoS 攻击?-知乎

DDoS话题 -知乎

DDOS攻击和CC攻击分别是怎样的?-知乎

DDOS百度百科,ddos在传输层使用各种方式,挤兑占用服务器资源,造成正常用户无法访问。

CC攻击百度百科,cc攻击是ddos攻击的一种方式,在应用层,使用代理方式对服务器资源进行占用挤兑,造成正常用户无法访问。

防御

DDOS 攻击的防范教程 – 阮一峰

付费产品

游戏盾 WAF CloudFlare BGP高防IP

WEB常见漏洞

汇总一些常用的渗透测试方法和工具,用于安全测试

kail linux 渗透测试专用操作系统

渗透测试

https://github.com/GoVanguard/legion

https://github.com/secforce/sparta

sqlmap sql注入扫描工具

DNSLog

是一种回显机制,攻击者可以通过DNS的解析日志来读取漏洞执行的回显结果。  

http://www.dnslog.cn/

http://ceye.io

网络安全应急响应实战手册

服务器挖矿木马[kthreaddi]处理记录

参考

[kthreaddi]挖矿病毒处理,终于解决了!

Linux – kthreaddi 进程导致CPU超高问题 处理记录

处理服务器恶意程序 kthreaddi挖矿

记服务器被入侵挖矿病毒kthreaddi处理解决过程思路

第一次处理

使用参考链接2方式,清除了定时任务,kill -s 9 进程之后正常了。由于同事离职没有收到反馈并继续观察。

第二次处理

后续接手项目,发现又有了继续按原方法清理定时任务,发现一条特别的定时任务,路径在/data/wwwroot/default/phpmyadmin 下,[kthreaddi]进程用户是www可能是通过php web方式注入的。看了一下使用oneinstack脚本后没有删除默认工具目录,于是删除default目录。然后禁用nginx默认虚拟主机使其无法通过ip访问,使用安全组关闭其他端口只开放常用端口。

kill 进程,发现没有用还是会自动重启,看了参考链接1的方式,得到灵感猜想可能有另一个进程负责重启[kthreaddi]进程。使用netstat -ltnp命令发现了一个非法进程监听 52281端口

于是kill 掉 非法进程,然后kill 掉 [kthreaddi] 进程,top命令观察发现正常了。

总结

此类木马通过定时任务重启,也可能结合systemd 或init脚本开机自启, 也可能使用其它伪装的正常进程来重启

延展阅读,更复杂案例top查看不到进程

应急响应:记一次花样贼多的挖矿病毒

Linux挖矿木马的技术演进探讨

Laravel 响应文件

以实时响应二维码为例

public function qrcode($activity_id, $invite)
    {   
        //二维码内容
        $activity_url = config('app.activity_url') . '?' . http_build_query(['id' => $activity_id, 'invite' => $invite]);
        //二维码图片文件的二进制数据
        $qrcodeStr = Qrcode::format('png')->size(80)->generate($activity_url);
        //直接响应文件,并设置对应的响应头
        return response($qrcodeStr)->withHeaders([
            'Access-Control-Allow-Origin' => '*',
            'Access-Control-Allow-Headers' => '*',
            'Access-Control-Allow-Methods' => 'GET,POST,PUT,DELETE,PATCH,OPTIONS',
            'Content-Type' => 'image/png;charset=utf-8',
            'Content-Disposition' => 'inline;filename="' . $invite . '.png"'
        ]);
    }

框架实现原理,如上图所示,使用Symfony 组件响应字符串数据,就相当于原生php的

header(....);//设置文件响应头
echo $bindata;//输出文件的二进制数据字符串

Laravel 在SLB下获取客户端IP和正确加载Https访问样式

如果项目部署在云服务负载均衡下,会导致无法获取正确的客户端IP地址

解决方案

参考文档https://learnku.com/docs/laravel/8.x/requests/9369#453bc9

修改 App\Http\Middleware\TrustProxies 中间件 信任所有代理#

如果你使用 Amazon AWS 或其他的「云」的负载均衡服务,你可能不知道负载均衡器的实际 IP 地址。在这种情况下,你可以使用 * 来信任所有代理:
/**
 * 此应用的信任代理
 *
 * @var string|array
 */
protected $proxies = '*';

上述配置还可以解决,telescope和horizon在SLB下通过https访问无法正确加载样式和js问题

获取IP其它解决方案

参考https://help.aliyun.com/document_detail/54007.html?spm=a2c4g.11186623.6.933.5b203253t8UrIO

背景信息

七层负载均衡(HTTP/HTTPS协议)服务需要对应用服务器进行配置,然后使用X-Forwarded-For的方式获取客户端的真实IP地址。真实的客户端IP存放在HTTP头部的X-Forwarded-For字段,格式如下:

X-Forwarded-For: 用户真实IP, 代理服务器1-IP, 代理服务器2-IP,...

当使用此方式获取客户端真实IP时,获取的第一个地址就是客户端真实IP。

配置Nginx服务器

  1. 执行如下命令,安装http_realip_module。 wget http://nginx.org/download/nginx-1.0.12.tar.gz tar zxvf nginx-1.0.12.tar.gz cd nginx-1.0.12 ./configure --user=www --group=www --prefix=/alidata/server/nginx --with-http_stub_status_module --without-http-cache --with-http_ssl_module --with-http_realip_module make make install kill -USR2 `cat /alidata/server/nginx/logs/nginx.pid` kill -QUIT `cat /alidata/server/nginx/logs/ nginx.pid.oldbin`
  2. 执行如下命令,打开nginx.conf文件。vi /alidata/server/nginx/conf/nginx.conf
  3. 在以下配置信息后添加新的配置字段和信息。 fastcgi connect_timeout 300; fastcgi send_timeout 300; fastcgi read_timeout 300; fastcgi buffer_size 64k; fastcgi buffers 4 64k; fastcgi busy_buffers_size 128k; fastcgi temp_file_write_size 128k;需要添加的配置字段和信息为: set_real_ip_from IP_address; real_ip_header X-Forwarded-For;说明 如果您要获取代理服务器的地址,可以将代理服务器的网段添加到set_real_ip_from <IP_address>,如负载均衡的IP地址段100.64.0.0/10(100.64.0.0/10 是阿里云保留地址,其他用户无法分配到该网段内,不会存在安全风险)和高防IP地址段。多个IP地址段用逗号分隔。
  4. 执行如下命令,重启Nginx。/alidata/server/nginx/sbin/nginx -s reload

然后获取请求头

//原生
$_SERVER['X-Forwarded-For'];
//laravel
$request->header('X-Forwarded-For');

HTTP监听访问正常但是HTTPS监听访问网址不加载样式

https://help.aliyun.com/document_detail/178368.htm?spm=a2c4g.11186623.2.17.116f7503fHVPRT

阿里云OSS相关问题

STS授权配置

参考:

https://help.aliyun.com/document_detail/100624.html?spm=a2c4g.11186623.6.708.576e6cb8K5XZME

  1. 登陆案例云账号进入《控制台》之后,按照下图指示进行创建RAM用户
  1. 配置用户权限,看下图
  1. 创建AccessKey ID、AccessKey Secret (注意这一步弹框生成的文件一定要保存下来),默认进来之后会有一个AccessKey ID先删除再创建;具体看下图

4、新建自定义权限策略

{    
 "Version": "1",    
 "Statement": [     
   {           
     "Effect": "Allow",           
     "Action": [             
        "oss:*"           
     ],           
     "Resource": [             
       "acs:oss:*:*:Bucket名称",             
       "acs:oss:*:*:Bucket名称/*"           
     ]     
   }    
]}

4、创建RAM账号

5、bucket与RAM绑定

跨域设置,点击上图中的跨域设置进行下图的配置

OSS文件自动下载问题

参考

https://help.aliyun.com/knowledge_detail/39545.html?spm=a2c4g.11186623.2.19.58241a216Srrvd

文件被强制下载可能的原因以下所示:

  • 使用OSS提供的默认域名,且没有经过其他配置。需要绑定自定义域名
  • 对应资源的Content-Type设置错误。
  • 对应资源的Content-Disposition设置错误。
  • CDN缓存了错误的Content-Type或者Content-Disposition。
  • 浏览器不支持该格式资源的展示。

其它常见问题

https://help.aliyun.com/knowledge_detail/142685.html?spm=a2c4g.11186623.6.1859.5af0606caO1MHy

Shell学习资料笔记

极客时间

https://github.com/geektime-geekbang/geekbanglinux/tree/master/ppt

Bash4.0 中文手册

Bash4.0 英文手册

https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html

Bash教程

https://wangdoc.com/bash/index.html

explainshell

https://explainshell.com/

Shell常用语法和案例

简单笔记

执行方式 bash ./xxx.sh ./xxx.sh (子进程运行) | source ./xxx.sh . xxx.sh (当前进程运行,会更改当前目录)

bash ./xxx.sh 可以不需要赋予执行权限 其它的方式需要 chmod u+x(r) xxx.sh

内建命令不需要创建子进程,对当前shell生效

环境变量配置

Linux环境变量设置/etc/profile、/etc/bashrc、~/.profile、~/.bashrc区别

Linux下/etc/profile 文件和/etc/profile.d区别以及相关说明

/etc/profile.d/目录增加脚本,或者/etc/profile增加内容后执行如下命令生效

source /etc/profile

编程领域技术栈

计算机专业相关领域

PC客户端

主要语言 C++/C#/Objective-C(swift) Python Java

MacOS

Mac桌面级程序开发用的开发语言开发工具和iOS开发都是一样,都是swift(或者Objective-C)和Xcode。

Windows

MFC

微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是微软公司提供的一个类库(class libraries),以C++类的形式封装了Windows API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。目前还占据着一定的市场,主要在军工、自动化等行业

Duilib

Duilib是一个Windows下免费开源的DirectUI界面库,由于简约易扩展的设计以及稳定高效的实现被各大互联网公司普遍接受,广泛应用于包括IM、视频客户端、股票行情软件、导航软件、手机辅助软件、安全软件等多个行业的众多pc客户端软件。

腾讯和网易基于此框架做了修改版

代表作品:

百度: PPS 爱奇艺 百度杀毒 百度卫士 91助手

腾讯: 微信 企业微信

阿里: 钉钉 支付宝安全控件 PP助手 优酷

详细软件列表

WPF 和 Windowsform (.Net Framework C#)

WPF,即windows presentation foundation,windows呈现基础,属于.net framework3.0,是微软推出取代winform的产品,能做到分离界面设计人员与开发人员的工作,提供多媒体交互用户图形界面,三大核心程序集是presentationcore、presentationFramework、windowsBase。

WinForm是·Net开发平台中对Windows Form的一种称谓。Windows窗体可用于设计窗体和可视控件,以创建丰富的基于Windows的应用程序。Windows窗体提供了一套丰富的控件,并且开发人员可以定义自己有特色的新的控件。WinForm控件是指以输入或操作数据的对象。比如:ComponentOne是.net平台下对数据和方法的封装。有自己的属性和方法。属性是控件数据的简单访问者。方法则是控件的一些简单而可见的功能。包含在 .NET Framework 中的 Windows窗体类旨在用于 GUI 开发。

WPF和winform最大的区别在于WPF底层使用的DirectX,winform底层使用的是GDI+,所以WPF的图形界面上更胜一筹。

GDI+(Graphics Device Interface)图形设备接口,它的主要任务是负责绘图程序之间的信息交换、处理,所有windows程序的图形输出。

DirectX(Direct Extension)多媒体编程接口,加强3D图形和声音效果,有很多API组成。按照性质分类可分为四大部分:显示部分,声音部分,输入部分和网络部分。


UWP (C#)

UWP即Windows 10中的Universal Windows Platform简称。即Windows通用应用平台,在Windows 10 Mobile/Surface(Windows平板电脑)/PC/Xbox/HoloLens等平台上运行,uwp不同于传统pc上的exe应用,也跟只适用于手机端的app有本质区别。它并不是为某一个终端而设计,而是可以在所有Windows10设备上运行。

Windows UI Library

Dephi

Delphi是一个集成开发环境(IDE),使用的是由传统Pascal语言发展而来的Object Pascal语言。它在本质上是一个代码编辑器而不是一种语言,但是由于Delphi是几乎是市场上唯一一个使用Pascal语言的产品,因此有的时候Delphi也成为了人们称呼Object Pascal的代名词。Borland公司已经把Object Pascal语言改称为Delphi语言。

在早期Windows客户端程序开发中,一直占据着主导地位,初学使用来说,非常容易(编程基础要求不高),自带有设计可视化界面和大量实用组件,只需简单拖拽,就可快速构建一个GUI程序,编译运行效率非常高,不过随着c#的大力发展,delphi的应用范围正在逐渐压缩,但对于Windows客户端程序来说,还是一个非常强有力的开发工具:

可在Windows3.x、Windows95、WindowsNT、WindowsXPWindowsVistaWindows7Windows8、Windows8.1、Windows10等环境下使用。当前,Delphi 也可以在LINUX平台上开发应用,其在LINUX上的对应产品Kylix

powerbuilder

这也是Windows平台下一个非常不错的客户端程序开发工具,和delphi类似,在早期的Windows桌面开发中,pb也一直扮演者重要角色,自带有设计界面和众多组件,只需简单拖拽,就可快速创建一个可视化界面,所见即所得,除此之外,报表查询功能强大,支持各种主流数据开发,对于Windows客户端程序设计来说,也是一个不错的工具,不过命运多舛,随着c#的兴起,也正在逐渐走向没落:

VB

Visual Basic(VB)是由微软公司开发的包含环境的事件驱动编程语言。它源自于BASIC编程语言。VB拥有图形用户界面(GUI)和快速应用程序开发(RAD)系统,可以轻易的使用DAO、RDO、ADO连接数据库,或者轻松的创建ActiveX控件。程序员可以通过拖动VB提供的组件快速创建一个应用程序。主要IDE是Visual Basic的集成开发工具。

Linux

GTK

GTK使用C语言开发,但是其设计者使用面向对象技术。也提供了C++gtkmm)、PerlRubyJavaPython(PyGTK)绑定,其他的绑定有AdaDHaskellPHP和所有的.NET编程语言与其他很多部件工具箱不同,GTK并不基于Xt。这一决策优劣互见:优点是GTK可以应用于其他系统,其灵活性也很强;而缺点就是它无法利用以传统方法为X11定制的X资源数据库。GTK最早应用于X Window System,如今已移植至其他平台,诸如Microsoft WindowsDirectFB,以及Mac OS X平台上的Quartz.

Glade是一个界面设计工具,但是它也包含了一种描述GUI界面的XML语言,它和libglade一起工作就可以直接使用GTK和GNOME控件;新的Glade-3不再直接支持生成编程语言源代码

KDE

跨平台

QT

NW.js

支持(Mac Windows Linux)v0.14.7 支持xp

迭代快,Web技术构建 源码加密 支持chrome扩展

不错的社区,包体积大 ,性能一般

代表作品 微信开发者工具

Electron

支持(mac,windows,linux,不支持xp)

web技术构建 活跃的社区 大型应用案例 包体积 性能一般

代表作品

Atom VsCode slack Twitch

Python GUI

Python 常用GUI控件集有PyQt、Tkinter、wxPython、PyGUI、Kivy。

Java

移动客户端

IOS

Android

跨平台

WEB端

服务端

算法/人工智能

大数据/云计算

运维/Devops/网络安全

嵌入式开发

驱动开发

参考链接

https://www.wukong.com/question/6768828415781896455/

https://www.cnblogs.com/wangle1001986/p/12839657.html

https://www.jianshu.com/p/6fab1fe260d2

linux开发环境 软件多版本共存方案

原理很简单,linux一切都是文件,多安装几个版本,软件名称和相关的配置用名字区分开即可。另一种方案是使用docker本文不做介绍

composer

运行composer 表示1版本 composer2表示2版本

PHP

多版本php共存,php是基于oneinstack安装的,通过软链接创建php默认版本,写个shell脚本方便切换。图中 php就是软链接。另一种现有php多版本解决方案是宝塔linux,是使用python写的运维工具

Mysql 非基础常用查询方式

where in 查询结果排序

默认情况下返回结果不会按照in语句内的数据顺序排序。如果需要返回结果按照in语句内的数据顺序排序,可以通过如下方式实现。

第一种 order by FIND_IN_SET(str,strlist)

select * from test where id in (2,1,4,3,5) order by find_in_set id (id,'2,1,4,3,5')

第二种 order by SUBSTRING_INDEX(str,delim,count)

select * from test where id in (2,1,4,3,5) order by substring_index('2,1,4,3,5',id,1)

第三种 order by field

select * from test where id in (2,1,4,3,5) order by field(id,2,1,4,3,5)

一对多 关联 对查询结果 用“多”表的字段进行排序

关系是一 的表 requirement_order

关系为多的表 goods_sku 关联字段为 requirement_id

对requirement_order表进行查询并按照 goods_sku 表中 price 价格进行倒排序

select * from requirement_order ORDER BY (select goods_sku.price from goods_sku where goods_sku.requirement_id = requirement_order.id limit 1) desc
一对多限制从表条数查询,比如查出所有分类以及每个分类下n条文章

表结构如下

分类表
文章表

方法一

laravel构造器写法

$category = Category::select('id', 'name')
    ->with([
     'article'=>function ($query) {
       $query->select('id', 'cat_id', 'title', 'author')
             ->whereRaw('(select count(*) from articles as articles2 where articles2.cat_id = articles.cat_id and articles2.id >= articles.id) <= ?', [3]);
                }
    ])
    ->get();

代码执行SQL

//查询分类
select `id`,`name` from `categories`
//查询分类下文章,每个分类下3条
select
  `id`,
  `cat_id`,
  `title`,
  `author`
from
  `articles`
where
  `articles`.`cat_id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
  and (
    select
      count(*)
    from
      articles as articles2
    where
      articles2.cat_id = articles.cat_id
      and articles2.id >= articles.id
  ) <= 3

如果只是查询一条的情况可以在with中使用groupBy从句

多对多限制从表条数查询,查出所有书单以及每个书单下n本书籍

表结构如下

书单表
书籍表
中间表

方法一

适用于数据量少的情况,数据多的时候查询慢

//书单模型BookList定义限制条数关联recommendBook
public function recommendBook()
{
  return $this->belongsToMany('App\Models\Book', 'book_list_has_books', 'booklist_id', 'book_id')
     ->select('books.id', 'name', 'cover', 'author')
     ->orderBy('book_list_has_books.sort', 'asc')
     ->latest('book_list_has_books.created_at')
     ->limit(10);
}

//控制器中查询
$booklists = BookList::select('id', 'title', 'position')
   ->latest()
   ->get()
   ->each(function ($booklist) {
        $booklist->load('recommendBook');
   });

代码执行SQL

循环查询

方法二

适用于从表数据量少的情况,相比第一种方法减少了查询次数,但是增加了从表数据量(因为是查所有),会占更多的用内存,可能导致内存泄露

$booklists = BookList::select('id', 'title', 'position')
  ->with([
     'listHasBook'=>function ($query) {
         $query->select('books.id', 'name', 'cover', 'author')
               ->orderBy('book_list_has_books.sort', 'asc')
               ->latest('book_list_has_books.created_at');
      }
   ])
  ->when($request->input('position'), function ($query) use ($request) {
      $query->where('position', $request->input('position'));
   })
  ->orderBy('sort', 'asc')
  ->latest()
  ->get()
  ->each(function (&$booklist) {
     $booklist->books = $booklist->listHasBook->slice(0, 10)->all();
     unset($booklist->listHasBook);
  });

执行SQL

只查询两次

如果只是查询一条的情况可以在with中使用groupBy从句

$booklist = BookList::select('id', 'title')
  ->with([
      'listHasBook'=>function ($query) {
           $query->select('books.id', 'cover')
                 ->groupBy('booklist_id');
       }
  ])

参考

https://blog.csdn.net/zdw19861127/article/details/80449691

https://bbs.csdn.net/topics/390969673?page=1

laravel with 查询列表限制条数