WEB应用常见漏洞

Sql注入

原理:利用网页程序没有对传参进行过滤,执行不允许的sql语句获取重要数据 百度百科 维基百科

防御

后端程序对请求参数进行严格过滤,使用框架的查询构造器和ORM操作Sql,禁止直接用代码拼接sql语句

SQL注入详解

XSS(Cross site scripting 跨站脚本攻击)

原理 前端运行了用户输入的恶意js脚本

MDN说明

防御

php函数htmlspecialchars转义html标签

过滤敏感js标签 ezyang/htmlpurifier

现代前端框架会自动处理xss问题

PHP防御 XSS 安全漏洞 – HTMLPurifier

如何防止XSS攻击?美团点评

PHP如何防止XSS攻击

CSRF(Cross-site request forgery 跨站请求伪造)

原理 MDN文档说明

防御

如何防止CSRF攻击?-美团点评

SSRF(Server-Side Request Forgery 服务器端请求伪造)

原理

防御

XXE(XML外部实体注入)

原理

防御

参考

Linux 文件权限

linux基本权限

ll 查看文件详情
说明

基本权限

左侧第一栏 -drwxr-xr-x表示权限,共10位字符

1.第一位字符表示文件类型

d 目录

– 文件

l 软链接

b 块设备(存储设备接口)文件 如,磁盘

c 串行端口设备 如 键盘 鼠标 usb 等

s 套接字文件 (socket) ,用于进程间通信

p 管道文件 FIFO pipe 用于解决多个程序访问一个文件时造成的错误问题

2.后九位没三位一组表示 user(所有者) group(所属组) other(其它人)的权限

3.操作权限

linux 三种权限

r : 文件=>读取文件内容( 可用命令 cat more head tail) 目录=>列出目录(ls ll)

w: 文件=>编辑 、新增、修改文件内容(vi echo). 不包括删除文件,删除文件需要文件所在目录(上级)拥有w 和 x权限 . 目录=>新建 删除文件目录, 重命名 移动 (touch rm mv cp)

写文件内容(文件本身) 和 创建删除文件 是不同的权限啊(所在目录),

x:执行权限

权限的作用范围仅限子级

PHP的运行模式

基本概念

CGI 通用网关接口  Common Gateway Interface

CGI 是Web 服务器运行外部程序的规范(协议),按CGI 编写的程序可以扩展服务器功能。CGI 应用程序能与浏览器进行交互,还可通过数据库API 与数据库服务器等外部数据源进行通信,从数据库服务器中获取数据。格式化为HTML文档后,发送给浏览器,也可以将从浏览器获得的数据放到数据库中。几乎所有服务器都支持CGI,可用任何语言编写CGI,包括流行的C、C ++、VB 和Delphi 等。CGI 分为标准CGI 和间接CGI两种。标准CGI 使用命令行参数或环境变量表示服务器的详细请求,服务器与浏览器通信采用标准输入输出方式间接CGI 又称缓冲CGI,在CGI 程序和CGI 接口之间插入一个缓冲程序,缓冲程序与CGI 接口间用标准输入输出进行通信。

功能,处理浏览器发送的表单请求,处理后并给浏览器响应(HTML).PHP就是C语言编写的CGI程序.其它ASP,JSP, .NET等

简而言之,来自客户端的HTTP POST请求将通过标准输入发送CGI程序HTML表单数据。其他数据(如URL路径和HTTP标头数据)显示为过程环境变量。

缺点

每有一个用户请求,都会先要创建CGI的子进程,然后处理请求,处理完后结束这个子进程(Fork-And-Execute模式). 这种方式开销大,请求过多和高并发是占用系统资源多.

CGI结构图

FastCGI  快速通用网关接口 FastCommonGatewayInterface

FastCGI(一种二进制协议,用于将交互式程序与Web服务器连接)像是一个常驻(long-live)型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一次(这是CGI最为人诟病的fork-and-execute 模式)。它还支持分布式的运算, 即 FastCGI 程序可以在网站服务器以外的主机上执行并且接受来自其它网站服务器来的请求。

每个单独的FastCGI进程可以在其生命周期内处理许多请求,从而避免了每个请求进程创建和终止的开销。同时处理多个请求可以通过几种方式实现:通过使用具有内部多路复用的单个连接(即通过单个连接的多个请求); 通过使用多个连接; 或者通过这些技术的组合。可以配置多个FastCGI服务器,从而提高稳定性和可扩展性。

进入正题

PHP结构图

SAPI

SAPI(Server Application Programming Interface,服务端应用编程端口 )是PHP的应用接口层,提供php和外部程序(web服务器和shell终端)通信的接口.PHP为不同的web服务器提供多种SAPI接口,运行模式指的就是PHP运行的是那种SAPI

获取SAPI http://php.net/manual/zh/function.php-sapi-name.php

 php_sapi_name() 和 PHP_SAPI 返回描述 PHP 所使用的接口类型(the Server API, SAPI)的小写字符串。 例如,CLI 的 PHP 下这个字符串会是 “cli”,Apache 下可能会有几个不同的值,取决于具体使用的 SAPI。 以下列出了可能的值。

可能返回的值包括了 aolserverapache、 apache2filterapache2handler、 caudiumcgi (直到 PHP 5.3), cgi-fcgicli、 cli-server、 continuityembedfpm-fcgi、 isapilitespeed、 milternsapi、 phttpdpi3webroxen、 thttpdtux 和 webjames

CLI模式

http://php.net/manual/zh/features.commandline.php

从版本 4.3.0 开始,PHP 提供了一种新类型的 CLI SAPI(Server Application Programming Interface,服务端应用编程端口)支持,名为 CLI,意为 Command Line Interface,即命令行接口。顾名思义,该 CLI SAPI 模块主要用作 PHP 的开发外壳应用。CLI SAPI 和其它 CLI SAPI 模块相比有很多的不同之处,我们将在本章中详细阐述。值得一提的是,CLI 和 CGI 是不同的 SAPI,尽管它们之间有很多共同的行为。

CLI-Server

PHP 5.4.0起, CLI SAPI 提供了一个内置的Web服务器。这个内置的Web服务器主要用于本地开发使用,不可用于线上产品http://php.net/manual/zh/features.commandline.webserver.php

CGI 模式

http://php.net/manual/zh/install.unix.commandline.php

LoadModule cgi_module modules/mod_cgi.so —cgi 模块 apache

FastCGI模式

FPM模式 

http://php.net/manual/zh/install.fpm.php

FPM(FastCGI 进程管理器)用于替换 PHP FastCGI 的大部分附加功能,对于高负载网站是非常有用的。

PHP-FPM 这种模型是非常典型的多进程同步模型,由一个master主进程多个worker进程组成.master进程创建时会创建一个sokect,但是不会处理请求,只负责调度worker进程

worker进程的生命周期,竞争的接受请求,解析FastCGI协议的数据,处理对应脚本,处理完成关闭请求,然后等待新的连接.同一时刻只能处理一个请求(同步阻塞IO).

master进程与worker进程之间不会直接通讯,master进程通过共享内存方式获取worker进程的信息,通过信号方式杀死worker进程.(进程间通讯)

缺点

每次启动都与需要重新加载php文件,浪费了一部分性能

ISAPI模式 (PHP 5.3)

ISAPI(Internet Server Application Program Interface)是微软提供的一套面向 Internet 服务的 API 接口,一个 ISAPI 的 DLL,可以在被用户请求激活后长驻内存,等待用户的另一个请求,还可以在一个 DLL 里设置多个用户请求处理函数,此外,ISAPI 的 DLL 应用程序和 WEB 服务器处于同一个进程中,效率要显著高于 CGI。由于微软的排他性,只能运行于 Windows 环境。

Module 模式  

http://php.net/manual/zh/install.unix.apache2.php

PHP 常常与 Apache 服务器搭配形成 LAMP 配套的运行环境。把 PHP 作为一个子模块集成到 Apache 中,就是 Module 模式,Apache 中的常见配置如下:

LoadModule php5_module modules/mod_php5.so

这使用了 LoadModule 命令,该命令的第一个参数是模块的名称,名称可以在模块实现的源码中找到。第二个选项是该模块所处的路径。如果需要在服务器运行时加载模块,可以通过发送信号 HUP 或者 AP_SIG_GRACEFUL 给服务器,一旦接受到该信号,Apache 将重新装载模块,而不需要重新启动服务器。通过注册到 apache2 的 ap_hook_post_config 挂钩,在 Apache 启动的时候启动此模块以接受 PHP 文件的请求。

例如,当客户端访问 PHP 文件时,Apache 就会调用 php5_module 来解析 PHP 脚本。Apache 每接收到一个请求,都会产生一个进程来连接 PHP 完成请求。在 Module 模式下,有时候会因为把 PHP 作为模块编进 Apache,而导致出现问题时很难定位是 PHP 的问题还是 Apache 的问题。

Apache MPM(多处理模块) 选择

要求 更高伸缩性的站点可以选择使用线程的 MPM,即 worker 或 event 需要可靠性或者与旧软件兼容的站点可以使用 prefork

运行方式总结

linux + nginx + php-fpm 主流 + 性能和兼容性兼顾

linux + nginx + php-cli + workman/webman 高性能 兼容原先的composer代码库

linux + nginx + php-cli (swoole-cli) 对旧代码兼容不好,如需要重建协程组件

linux + apache mpm event + php-fpm

linux + apache mpm + mod_php

I/O性能优先级

swoole(cli) > php-fpm > mod_php

相关参考

深入理解Zend SAPIs(Zend SAPI Internals) 鸟哥博客

PHP 运行模式

mod_php和mod_fastcgi和php-fpm的介绍,对比和性能数据

Apache的三种MPM模式比较:prefork,worker,event

nginx 让users有权限启动的两种方法

普通用户在restart和reload nginx时,会报错:

nginx: [warn] the “user” directive makes sense only if the master process runs with super-user privileges, ignored in /usr/local/nginx/conf/nginx.conf:2

我又不能给开发人员root权限,没办法,只好这么做。

原因是:默认情况下Linux的1024以下端口是只有root用户才有权限占用

方法一:

所有用户都可以运行(因为是755权限,文件所有者:root,组所有者:root)

chown root.root nginx
chmod 755 nginx
chmod u+s nginx

方法二:

仅 root 用户和 wyq 用户可以运行(因为是750权限,文件所有者:root,组所有者:www)

chown root.www nginx
chmod 750 nginx
chmod u+s nginx

转载原文https://blog.csdn.net/yan7895566/article/details/79876059

Maatwebsite / Laravel-Excel 扩展包导入导出数据

文档 https://laravel-excel.maatwebsite.nl/3.1/getting-started/

github https://github.com/Maatwebsite/Laravel-Excel

环境要求

  • PHP: ^7.0
  • Laravel: ^5.5
  • PhpSpreadsheet: ^1.4
  • PHP扩展已php_zip启用
  • PHP扩展已php_xml启用
  • PHP扩展已php_gd2启用

安装

composer require maatwebsite/excel

laravel5.5已下版本手动添加ServiceProvider config/app.php

'providers' => [
    /*
     * Package Service Providers...
     */
    Maatwebsite\Excel\ExcelServiceProvider::class,
]

添加Facade config/app.php

'aliases' => [
    ...
    'Excel' => Maatwebsite\Excel\Facades\Excel::class,
]

发布配置

php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider" --tag=config
或者
php artisan vendor:publish 然后手动选择

生成config/excel.php配置文件

导出

创建导出类

php artisan make:export UsersExport --model=App/User

导出格式

https://laravel-excel.maatwebsite.nl/3.1/exports/export-formats.html

导出方式

1.直接响应下载文件

use App\Exports\UsersExport;
use Maatwebsite\Excel\Facades\Excel;
use App\Http\Controllers\Controller;

class UsersController extends Controller 
{
    public function export() 
    {
        return Excel::download(new UsersExport, 'users.xlsx');
    }
}

2.存储到磁盘

public function storeExcel() 
{
    // Store on default disk
    Excel::store(new InvoicesExport(2018), 'invoices.xlsx');
    
    // Store on a different disk (e.g. s3)
    Excel::store(new InvoicesExport(2018), 'invoices.xlsx', 's3');
    
    // Store on a different disk with a defined writer type. 
    Excel::store(new InvoicesExport(2018), 'invoices.xlsx', 's3', Excel::XLSX);
}
  • 参数1为导出类
  • 参数2为文件名
  • 参数3为laravel存储的磁盘
  • 参数4为导出格式 详情看配置文件

从集合导出

<?php

namespace App\Exports;

use App\User;
use Maatwebsite\Excel\Concerns\FromCollection;

class UsersExport implements FromCollection
{
    public function collection()
    {
        return User::all();
    }
}
  • 实现 FromCollection 接口 的collection方法
  • collection方法内可以是任何Eloquent ORM的查询 get() first() all() pluck()等方法的返回结果(collection)也可以是通过构造方法传入的collection

从查询导出

namespace App\Exports;

use App\Invoice;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\Exportable;

class InvoicesExport implements FromQuery
{
    use Exportable;

    public function query()
    {
        return Invoice::query();
    }
}
  • 实现Maatwebsite\Excel\Concerns\FromQuery 的 query方法
  • query 方法内return任何Laravel Eloquent ORM的查询构造器的方法,除了获取集合的get() first() all() pluck()等方法

从视图导出

将html表格转换成excel表格,不推荐使用,不灵活,此功能对html结构有要求

队列导出

支持 FromCollection 和 FromQuery

namespace App\Exports;

use App\User;
use Maatwebsite\Excel\Concerns\FromCollection;
use Illuminate\Contracts\Queue\ShouldQueue;

class UsersExport implements FromCollection, ShouldQueue
{
    /**
     * @return \Illuminate\Support\Collection
     */
    public function collection()
    {
        return User::all();
    }
}

队列直接下载导出 控制器代码

 public function export(Request $request, Excel $excel)
 {
    return $excel->download(new UsersExport(), 'users.xlsx');
 }

队列导出存储到磁盘

public function store(Request $request)
{
   ini_set('memory_limit', '1024M');
   $result = Excel::store(new UsersExport(), 'users_store'.date('YmdHis').'.xlsx', 'public');
}
  • 数据量大时,有时会超出内存限制需要设置内存,后来没复现,没找到原因
  • 从 collection导出的方式,成功后没有发现导出excel文件,后来没复现,没有找到原因

设置表头

class InvoicesExport implements WithHeadings
{   
    public function headings(): array
    {
        return [
            '对应ExcelA列',
            '对应ExcelB列',
            ...
        ];
    }
}

要实现Maatwebsite\Excel\Concerns\WithHeadings的headings方法

每行字段值映射

public function map($code): array
{
    return [
       $A,
       (string) $B,
       0 == $C ? '未使用' : '使用',
    ];
}

要实现 Maatwebsite\Excel\Concerns\WithMapping的map方法

可以对具体值做处理

字段格式化

https://docs.laravel-excel.com/3.1/exports/column-formatting.html

namespace App\Exports;

use PhpOffice\PhpSpreadsheet\Shared\Date;//处理时间格式的类,
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;//处理数字格式
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use Maatwebsite\Excel\Concerns\WithMapping;

class InvoicesExport implements WithColumnFormatting, WithMapping
{
    public function map($invoice): array
    {
        return [
            $invoice->invoice_number,
            Date::dateTimeToExcel($invoice->created_at),//时间处理
            $invoice->total
        ];
    }
    
    public function columnFormats(): array
    {
        return [
            'B' => NumberFormat::FORMAT_DATE_DDMMYYYY, 
            'C' => NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE,
             //I为列头标识格式化成文本常用的比如手机号或订单号会转为科学计数法,这样可以解决
            'I' => NumberFormat::FORMAT_TEXT,
        ];
    }
}

处理日期时,建议在映射中PhpOffice\PhpSpreadsheet\Shared\Date 使用以确保正确解析日期。

设置列宽度

自动设置尺寸

namespace App\Exports;

use Maatwebsite\Excel\Concerns\ShouldAutoSize;

class InvoicesExport implements ShouldAutoSize
{
    ...
}

自定义宽度

namespace App\Exports;

use Maatwebsite\Excel\Concerns\WithColumnWidths;

class InvoicesExport implements WithColumnWidths
{
    public function columnWidths(): array
    {
        //A B 是列的标识头
        return [
            'A' => 55,
            'B' => 45,            
        ];
    }
}

常用配置修改

 /*
  |--------------------------------------------------------------------------
    Heading Row Formatter
  |--------------------------------------------------------------------------
  |
  | Configure the heading row formatter. 
  | Available options: none|slug|custom
  |
  */
  'heading_row' => [
      'formatter' => 'none',//不格式化,这样可以导入中文标题头excel
  ],

   /*
    |--------------------------------------------------------------------------
    | Transaction Handler
    |--------------------------------------------------------------------------
    |
    | By default the import is wrapped in a transaction. This is useful
    | for when an import may fail and you want to retry it. With the
    | transactions, the previous import gets rolled-back.
    |
    | You can disable the transaction handler by setting this to null.
    | Or you can choose a custom made transaction handler here.
    |
    | Supported handlers: null|db
    |
    */
    'transactions' => [
        'handler' => 'null', //取消事物,不回滚,成功导入的数据不会被回滚
    ],

MySql索引的使用总结

所有存储引擎都支持每个表至少 16 个索引,总索引长度至少为 256 字节。

组合索引KEY(col1,col2) 联合主键索引 PARIMARY KEY( col1,col2) 

最左匹配原则

创建了key(k1,k2,k3),相当于创建了(k1)、(k1,k2) 和 (k1,k2,k3) 三个索引

索引全部命中的情况where条件不区分顺序 where k1 = xxx and k2 = xxx and k3 = xxx 等同于 where k3 = xxx and k2 = xxx  and k1 = xxx 查询优化器会处理并使用索引

where k1 = xxx 或 where k1 = xxx and k2 = xxx 使用索引 where k2 = xxx 或 where k3 = xxx 无法使用索引

当查询优化器发现最优索引时,并不会遵循最左匹配原则,而是使用最优查询,如下图k1,k2,k3为连续字段时,不按最左匹配查询还是会命中索引,此时k1,k2,k3被查询优化器当成了一个字段,单次查询k1,k2,k3都会命中

EXPLAIN select * from 3k where k2 = 'sdfdsa'

当k1,k2,k3不在连续中间被其它字段隔开时

相同的查询语句将不会命中索引

联合索引,那么 key 也由多个列组成,同时,索引只能用于查找 key 是否存在(相等),遇到 范围查询(>、<、between、like 左匹配)等就不能进一步匹配了,后续退化为线性查找。因此,列的排列顺序决定了可命中索引的列数。

如有索引 (a, b, c, d),查询条件 a = 1 and b = 2 and c = 3 and d > 4,则会在每个节点依次命中 a、b、c,无法命中 d。也就是最左前缀匹配原则。

不需要考虑 =、in 等的顺序,MySQL 会自动优化这些条件的顺序,以匹配尽可能多的索引列。

如有索引 (a, b, c, d),查询条件 c > 3 and b = 2 and a = 1 and d < 4 与 a = 1 and c > 3 and b = 2 and d < 4 等顺序都是可以的,MySQL 会自动优化为 a = 1 and b = 2 and c > 3 and d < 4,依次命中 a、b。

离散度高原则,选择性(离散性)高的优先,即数据重复率低的列,像性别字段只有男/女两个值,因此选择性很差

离散度的公式是 count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是 1,而一些状态、性别字段可能在大数据面前区分度就是 0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要 join 的字段我们都要求是 0.1 以上,即平均 1 条扫描 10 条记录。

索引前缀

字符串字段过长时可以使用,索引前缀,截取字段前一部分的值作为索引

CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));

Range类型 要使用单字段索引

当使用 =、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN、LIKE 或 IN() 运算符中的任何一个将键列与常量进行比较时,可以使用范围

where min <= 1 and max >= 1 语句使用min和max联合索引并不会生效,应该使用min和max的两个单字段索引

索引失效情况总结

查询条件包含 or,会导致索引失效

隐式类型转换,会导致索引失效,where条件左边字段类型为字符串类型时,传入其他类型会触发

like 通配符会导致索引失效,注意:”ABC%” 不会失效,会走 range 索引,”% ABC” 或 “%ABC%” 索引会失效

联合索引,最左匹配原则被中断时

对索引字段进行函数运算,列运算(算术,逻辑,移位等) 注意是对字段做运算,对字段的值做运算时并不影响,如下图

索引字段上使用(!= 或者 < >,not in)时,会导致索引失效

索引字段上使用 is null, is not null,可能导致索引失效

相 join 的两个表的字符编码不同,不能命中索引,会导致笛卡尔积的循环计算

mysql 优化器判断使用全表扫描要比使用索引快,则不使用索引

简单索引和联合索引如何抉择?

能扩展就不要新建索引。如果已有索引 (a),想建立索引 (a, b),尽量选择修改索引 (a) 为索引 (a, b),这样占用空间最小效果一致。

如果已有索引 (a, b),则不需要再建立索引 (a),但是如果有必要,则仍然需考虑建立索引 (b)。

索引尽量少原则

虽说索引可以加速查询,但索引未必是越多越好,因为:

  • 第一点、数据的增删都会涉及到随索引的修改,索引越多维护成本越高,所以频繁进行数据操作的表,不要建立太多的索引;
  • 第二点、索引越多也意味着存储空间需要越大;

因为索引是有代价的,所以用不到的索引,也需要清理掉。

如何定位哪些页面和接口需要加索引?

最简单直接方法是:往数据库里生成 100 万条数据,然后做黑盒测试。

数据有了以后,假装你是一个正常的用户,然后不断地点来点去,做各种操作,点赞、收藏、发文章、评论等,看看哪个动作或者页面加载很慢,就记录下来

如果使用laravel框架可以用telescope或者debug工具查看执行的sql语句,对访问频率高的接口和页面,增加索引,优化查询

参考

盘点那些被问烂了的 Mysql 面试题

MySQL 规约(转自阿里巴巴 Java 开发手册)

官方手册优化与索引

laravel优化教程

composer 加速扩展包—— hirak/prestissimo

在用composer过程中会经常出现安装慢的情况。项目依赖的扩展包过多时,耗时很长,影响部署和开发。

1.是因为网络镜像问题,可以通过设置镜像源解决 https://www.yangliuan.cn/?p=172

2.因为 Composer 是单进程方式下载的, Composer 安装完一个依赖,才回去下载并安装另一个依赖

解决方案使用composer 扩展包 prestissimo

项目地址:https://github.com/hirak/prestissimo

 安装  建议采用全局安装
composer global require hirak/prestissimo

卸载

composer global remove hirak/prestissimo

基准测试 案例

$ composer create-project laravel/laravel laravel1 --no-progress --profile --prefer-dist

288s -> 26s

配置

支持composer 配置项 无需任何特殊配置 composer配置

Composer 配置镜像源

现代php开发都基于composer,由于”墙”的存在,影响了安装或更新扩展包的时候用。因此使用composer时需要配置一下国内镜像

配置镜像

全局方式

composer config -g repo.packagist composer 镜像url

该指令会修改composer 全局配置文件中的镜像url

如图 repositories 配置中 packagist url项

配置当前项目

composer config repo.packagist composer 镜像URL

该指令会在当前项目的composer.json中修改镜像url

国内镜像

镜像名地址赞助商更新频率备注
阿里云 Composer 镜像https://mirrors.aliyun.com/composer/阿里云96 秒推荐
腾讯云 Composer 镜像https://mirrors.cloud.tencent.com/composer/腾讯云24 小时
PHP 国内 Composer 镜像https://packagist.phpcomposer.com仁润股份24 小时不稳定
华为云 Composer 镜像https://repo.huaweicloud.com/repository/php/
https://mirrors.huaweicloud.com/repository/php/
华为云未知未知

如果使用ubuntu和linux开发可以用shell写个切换镜像脚本 composer.sh

Ubuntu 配置环境变量

参考资料 https://www.jianshu.com/p/12fbfa8c7489

以composer 为例

本文修改的是/etc/profile 环境变量,其它环境变量请看参考文章

执行sudo vim /etc/profile

以composer为例,文件在最后一行添加export PATH =”/home/grace/.config/composer/vendor/bin” 如图所示,多个目录用英文冒号分割: .

保存之后重启即可

其它方式生效 source /etc/profile ,会在当前终端生效

后来经过测试,执行source后不需要重启服务器。退出当前会话重新登录即可。如果是图形界面登出桌面,重新登录。如果是终端exit或关闭 ,重新使用ssh登录即可

ubuntu root用户找不到环境变量解决方案

编辑 /root/.bashrc 文件,文件末尾添加 source /etc/profile 保存 执行更新:source /root/.bashrc 或者重启

laravel-cors 扩展包

跨域资源共享 参考 https://www.yangliuan.cn/?p=141

公司采用前后端分类的开发方式,每次部署项目都需要设置nginx配置或添加php header响应非常麻烦,于是在github找了一个用于设置cors跨域的扩展包,很好用。写下来备忘。

github地址https://github.com/barryvdh/laravel-cors

1.composer require barryvdh/laravel-cors

 在laravel项目执行安装,如果使用的是laravel 5.5以下版本 请在config/app.php中的providers 数组中添加 Barryvdh\Cors\ServiceProvider::class,注册该服务提供者

2.php artisan vendor:publish –provider=”Barryvdh\Cors\ServiceProvider”

 执行发布配置文件,该命令会在config目录下生成配置文件

3.根据你的需求讲扩展包中的 \Barryvdh\Cors\HandleCors::class,  中间件添加到 全局中间件 ,中间组,路由中间件中。

如图所示添加到api路由组中间件中

4.根据需求修改配置文件,设置允许的请求来源,请求头 和请求方

 特别注意,该扩展包会在浏览器使用ajax请求时,根据配置自动添加响应头,非ajax请求并不会添加响应头.

  使用不允许的请求源或请求头和方法是会返回403

补充

该扩展包在异常响应时不会响应设置的跨域请求头,尤其是在结合框架自带的表单验证响应422时,会造成跨域

建议使用php原生header写法

laravel 7以后 官方已经集成了该扩展包