首页
统计
壁纸
追番记录
优秀博主
关于
推荐
导航
工具
音乐解锁
Search
1
NAS的简单介绍
729 阅读
2
网站环境一键部署工具推荐
505 阅读
3
tp5-模型数据处理
404 阅读
4
win10镜像
359 阅读
5
第20200225期-电脑壁纸-P10
350 阅读
PHP
闲谈杂料
硬件系统
美图
ThinkPHP
笔记
数据库
Lua
登录
Search
标签搜索
ThinkPHP
MySQL
Laravel
PHP
API
GIT
Windows10
markdown
Web
跨域
ajax
小程序
壁纸
Linux
jsonp
try
异常
Dcat
UEFI
win10
phpfunny
累计撰写
104
篇文章
累计收到
24
条评论
首页
栏目
PHP
闲谈杂料
硬件系统
美图
ThinkPHP
笔记
数据库
Lua
页面
统计
壁纸
追番记录
优秀博主
关于
推荐
导航
工具
音乐解锁
搜索到
31
篇与
的结果
2024-11-13
关于Larave中.env读取偶发性失效问题
相关问题.env设置了自定义参数,但env()函数读取失败只获取默认值编辑.env没有生效其他env问题问题描述在配置完.env后(增加了一些自定义KEY) 在程序中使用env()助手函数没有获取的键值。在Larave文档相关操作说明(config):需要删除env缓存文件并重新生成。执行发现依然没有生效。可是检查.env文件参数是没问题的,了解env()和config()区别后更是不解,明明用的env()的助手行数直接获取env文件中的参数,和缓存没有关系,但实际发现确实读取不到,获取的是env()参数二设置的默认值。最终也很疑惑希望知情之人能告知一二。解决过程检查.env配置文件中设置正确的参数SERVICE_IP="42.XXX.XXX.163" TENCENTCLOUD_SECRET_ID=AKIDgXXXXXXXXXXXXXXXXXXXXXXXXMtENL4 TENCENTCLOUD_SECRET_KEY=cwDPciXXXXXXXXXXXXXXXVYXLwKVWM TENCENTCLOUD_CAPTCHA_APPID=1900000000 TENCENTCLOUD_APPSECRET_KEY=hi8XXXXXXXXXXXXXXXX6tqbU WECHAT_APP_ID=wx000000000000ce WECHAT_APP_SECRET=80cXXXXXXXXXXXXXXfb18 WECHAT_TOKEN=76976000000000000000acb834a WECHAT_ENCODING_AES_KEY=u7u2B00000000000000001jZrv9设置config配置参数/config/services.phpreturn [ ... 'easywechat' => [ 'official_account' => [ 'app_id' => env('WECHAT_APP_ID', ''), 'secret' => env('WECHAT_APP_SECRET', ''), 'token' => env('WECHAT_TOKEN', ''), 'aes_key' => env('WECHAT_ENCODING_AES_KEY', '') ], ], 'tencentcloud' => [ 'secret_id' => env('TENCENTCLOUD_SECRET_ID', ''), 'secret_key' => env('TENCENTCLOUD_SECRET_KEY', ''), 'captcha_appid' => env('TENCENTCLOUD_CAPTCHA_APPID', ''), 'appsecret_key' => env('TENCENTCLOUD_APPSECRET_KEY', '') ], 'service_ip' => env('SERVICE_IP', '') ];删除config缓存并重新生成#清除config缓存文件 php artisan config:clear #生成config缓存文件 php artisan config:cache测试请在需要获取参数的地方使用config()助手函数dd(config('services.tencentcloud.captcha.appid')); dd(config('services.service_ip'));最优雅的方式env()方法不要在业务代码中使用,只在配置文件中使用。拓展一,最优雅获取配置方式上述"解决过程"为最佳方式二,助手函数中env()和config()区别助手函数用途用法示例env()函数用于直接从 .env 文件中读取环境变量。它主要用于在配置文件中读取环境变量,以便在不同的环境中使用不同的配置值。env('API_KEY', 'default_value');在.env文件中写法 API_KEY=your_api_keyconfig()用于从配置文件中读取配置值。配置文件位于 config 目录下,每个文件对应一个特定的配置领域。config('app.api_key');在/config/app.php写法 return ['api_key' => env('API_KEY', 'default_key')];两者区别读取来源不同:env() 从 .env 文件中读取环境变量。config() 从 config 目录下的配置文件中读取配置值。使用场景不同:env() 通常用于在配置文件中读取环境变量,以便在不同的环境中使用不同的配置值。config() 用于在代码中读取配置文件中的配置值。缓存机制不同:env() 不会被缓存,每次调用都会从 .env 文件中读取。config() 会被缓存,使用 php artisan config:cache 命令生成的缓存文件 bootstrap/cache/config.php 中读取配置值,提高性能。三,关于env()获取为空原因
2024年11月13日
8 阅读
0 评论
0 点赞
2024-07-12
Dcat处理tinymce图片上传
tinymce 插件内置在dcatadmin中。tinymce图片上传默认路径和dcatadmin图片上传保存路径不一致。 需要更改tinymce上传配置app/Admin/bootstrap.php 文件处修改 Editor 组件样式use Dcat\Admin\Form\Field\Editor; Editor::resolving(function (Editor $editor) { $editor->options([ 'plugins' => [ 'advlist', 'autolink', 'link', 'image', 'media', 'lists', 'preview', 'code', 'help', 'fullscreen', 'table', 'autoresize', 'codesample', 'batchUploadImage', ], 'toolbar' => [ 'undo redo | preview fullscreen | styleselect | fontsizeselect bold italic underline strikethrough forecolor backcolor | link image batchUploadImage media blockquote removeformat codesample', 'alignleft aligncenter alignright alignjustify| indent outdent bullist numlist table subscript superscript | code', ], 'min_height' => 400, 'save_enablewhendirty' => true, 'convert_urls' => false, ]); });
2024年07月12日
8 阅读
0 评论
0 点赞
2024-05-17
使用Laravel事件系统
比如在用户注册时候需要一些额外的操作。 使用laravel中的事件系统去创建事件和监控器去实现便于开发和维护。文档介绍 https://learnku.com/docs/laravel/8.x/events/9391#01e998创建事件和监控器#指令创建事件 php artisan make:event UserRegistered #指令创建监控器 php artisan make:listener CreateUserDatabase --event=UserRegistered事件案例代码:<?php namespace App\Events; class UserRegistered { /** * Create a new event instance. * * @return void */ public function __construct(public int $userId) { //Log::debug('UserRegistered注册事件'); } } 监控案例代码:<?php namespace App\Listeners; use App\Events\UserRegistered; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\DB; class CreateUserDatabase implements ShouldQueue { /** * 任务将被发送到的队列的名称 * * @var string|null */ public $queue = 'listeners'; /** * Create the event listener. * * @return void */ // public function __construct(){} /** * Handle the event. * * @param \App\Events\UserRegistered $event * @return void */ public function handle(UserRegistered $event) { Log::debug('触发了用户注册事件 USER_ID: ' . $event->userId); DB::table('users')->where('id', $event->userId)->update(['deleted_at' => time()]); try { DB::beginTransaction(); #创建新用户专属数据库 // DB::select('select * from users where active = ?', [1]); #执行sql原生操作 #创建上报字段信息表 DB::commit(); } catch (\Exception $e) { DB::rollBack(); } } /** * 获取监听器队列的名称 * * @return string */ // public function viaQueue() // { // return $this->queue; // } }配置事件与监听器的绑定打开 app/Providers/EventServiceProvider.php 文件。protected $listen = [ UserRegistered::class => [ CreateUserDatabase::class, ], ];使用事件在想要触发的位置去进行触发事件的监听use App\Events\UserRegistered; //注册 public function register(Request $request) { $input = $request->only('account_name', 'password'); event(new UserRegistered(2)); #2为传递的用户ID return $this->services->register($input); }事件执行方式事件执行有两种方式方式一,同步触发(同步执行)这是最直接的触发方式,事件在触发后,相应的监听器会立即执行,执行过程与触发事件的代码在同一请求生命周期内完成。同步触发适用于那些执行速度较快、不影响用户体验的操作。同步触发事件的典型代码示例如下:use App\Events\SomeEvent; // 触发事件 event(new SomeEvent($data));方式二,异步触发(队列方式)对于耗时较长的事件处理逻辑,如发送邮件、短信通知、复杂的数据处理等,推荐使用异步触发方式,以避免阻塞用户的请求响应。Laravel 提供了队列(Queue)系统来实现异步处理。异步触发事件通常有两种模式:使用 Queueable 特性在事件类中使用 Illuminate\Queue\InteractsWithQueue 特性,并实现 shouldQueue 方法,使事件变为可队列化的。然后,当触发该事件时,Laravel 会自动将其推送到队列中异步处理。use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; class SomeEvent implements ShouldQueue { use Dispatchable, InteractsWithQueue; // ...构造函数和属性... public function handle() { // 事件处理逻辑 } }在监听器中使用队列即使事件本身没有实现 ShouldQueue 接口,也可以在监听器的 handle 方法中将耗时操作放入队列。这要求监听器实现 ShouldQueue 接口,并配置监听器为异步处理。use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Queue\InteractsWithQueue; class SomeEventListener implements ShouldQueue { use InteractsWithQueue; public function handle(SomeEvent $event) { // 将耗时操作放入队列处理 SomeLongRunningJob::dispatch($event->data); } }触发队列任务在上述异步处理方式中,提到的 SomeLongRunningJob 是一个队列任务的例子。你可以使用 Laravel 的任务调度器(Jobs)配合队列来进一步处理复杂的异步逻辑。创建队列任务并将其加入队列的代码示例如下:use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\Jobs\Job; use Illuminate\Contracts\Queue\ShouldQueue; class SomeLongRunningJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, SerializesModels; public $data; public function __construct($data) { $this->data = $data; } public function handle() { // 执行耗时任务 } } // 触发队列任务 SomeLongRunningJob::dispatch($data);总结Laravel 提供了灵活的事件触发机制,无论是同步还是异步处理,都能通过简洁的API实现复杂逻辑的解耦和高效执行。
2024年05月17日
8 阅读
0 评论
0 点赞
2023-05-22
Dcat菜单列表重写
前提在项目中使用的dcatadmin框架多用户模式,只有一个单后台,用户角色分为:administrator(超管), member(会员), sub_account(会员子账号)每个会员及其子账号 只能看见自己创建的自定义表单在菜单显示(例如A会员和A会员创建的A1子会员,A2子会员 大家登录后看见都是一样的, 但是A会员和B会员看见的自定义表单菜单是不一样的)。仔仔细细看了下文档 只能动态添加菜单,可是不能根据当前登录用户来决定菜单是否显示,此时脑中浮现两种方式,方式一,在创建自定义表单的时候,同时往admin_menu,admin_role,admin_role_users等表中插入菜单关联数据需要操作3-5个关系表(菜单,角色,权限及其关系表),然后每个用户都创建一个单独的与用户对应的角色,在将角色和菜单关联,让dcat来自动显示是否显示。 但是这种做需要同时操作的数据库表多张,关系繁琐弊端较多 妥妥的下下测。方式二,重构菜单列表,在渲染菜单列表的时候使用文档中通过Menu::add接口动态添加菜单 然后我也就不需要在把创建的自定义表单,单独的存入admin_menu中菜单中。仅仅只需要获取当前登录用户然后在原本菜单列表渲染后面动态add一份自定义表单即可。创建任务:在/App/Admin中重写菜单列表渲染下面即是我阅读dcat源码后进行的操作过程:复制数据格式源位置/vendor/dcat/laravel-admin/src/Layout/Menu.php复制到/app/Admin/Layout/Menu.php<?php /** * 菜单列表重写 */ namespace App\Admin\Layout; //namespace Dcat\Admin\Layout; use Dcat\Admin\Admin; use Dcat\Admin\Support\Helper; use Illuminate\Support\Facades\Lang; class Menu { protected static $helperNodes = [ [ 'id' => 1, 'title' => 'Helpers', 'icon' => 'fa fa-keyboard-o', 'uri' => '', 'parent_id' => 0, ], [ 'id' => 2, 'title' => 'Extensions', 'icon' => '', 'uri' => 'auth/extensions', 'parent_id' => 1, ], [ 'id' => 3, 'title' => 'Scaffold', 'icon' => '', 'uri' => 'helpers/scaffold', 'parent_id' => 1, ], [ 'id' => 4, 'title' => 'Icons', 'icon' => '', 'uri' => 'helpers/icons', 'parent_id' => 1, ], ]; protected $view = 'admin::partials.menu'; public function register() { if (! admin_has_default_section(Admin::SECTION['LEFT_SIDEBAR_MENU'])) { admin_inject_default_section(Admin::SECTION['LEFT_SIDEBAR_MENU'], function () { $menuModel = config('admin.database.menu_model'); return $this->toHtml((new $menuModel())->allNodes()->toArray()); }); } //================================================================================ //在此处追加-添加自定义的菜单 $this->add([ [ 'id' => 400, // 此id只要保证当前的数组中是唯一的即可 'title' => '测试菜单999', 'icon' => 'fa-file-text-o', 'uri' => '', 'parent_id' => 0, 'permission_id' => '7', // 与权限绑定 'roles' => 'user2', // 与角色绑定 ], [ 'id' => 401, // 此id只要保证当前的数组中是唯一的即可 'title' => '测试菜单-item', 'icon' => 'fa-file-text-o', 'uri' => '', 'parent_id' => 400, 'permission_id' => '7', // 与权限绑定 'roles' => 'user2', // 与角色绑定 ] ],20); //=================================================================================== //\Illuminate\Support\Facades\Log::debug('111111111'); if (config('app.debug') && config('admin.helpers.enable', true)) { $this->add(static::$helperNodes, 20); //$this->add(static::$helperNodes, 20); //$this->add(static::$helperNodes, 20); //$this->add(static::$helperNodes, 20); //$this->add(static::$helperNodes, 20); } } /** * 增加菜单节点. * * @param array $nodes * @param int $priority * @return void */ public function add(array $nodes = [], int $priority = 10) { admin_inject_section(Admin::SECTION['LEFT_SIDEBAR_MENU_BOTTOM'], function () use (&$nodes) { return $this->toHtml($nodes); }, true, $priority); } /** * 转化为HTML. * * @param array $nodes * @return string * * @throws \Throwable */ public function toHtml($nodes) { $html = ''; foreach (Helper::buildNestedArray($nodes) as $item) { $html .= $this->render($item); } return $html; } /** * 设置菜单视图. * * @param string $view * @return $this */ public function view(string $view) { $this->view = $view; return $this; } /** * 渲染视图. * * @param array $item * @return string */ public function render($item) { return view($this->view, ['item' => &$item, 'builder' => $this])->render(); } /** * 判断是否选中. * * @param array $item * @param null|string $path * @return bool */ public function isActive($item, ?string $path = null) { if (empty($path)) { $path = request()->path(); } if (empty($item['children'])) { if (empty($item['uri'])) { return false; } return trim($this->getPath($item['uri']), '/') == $path; } foreach ($item['children'] as $v) { if ($path == trim($this->getPath($v['uri']), '/')) { return true; } if (! empty($v['children'])) { if ($this->isActive($v, $path)) { return true; } } } return false; } /** * 判断节点是否可见. * * @param array $item * @return bool */ public function visible($item) { if ( ! $this->checkPermission($item) || ! $this->checkExtension($item) || ! $this->userCanSeeMenu($item) ) { return false; } $show = $item['show'] ?? null; if ($show !== null && ! $show) { return false; } return true; } /** * 判断扩展是否启用. * * @param $item * @return bool */ protected function checkExtension($item) { $extension = $item['extension'] ?? null; if (! $extension) { return true; } if (! $extension = Admin::extension($extension)) { return false; } return $extension->enabled(); } /** * 判断用户. * * @param array|\Dcat\Admin\Models\Menu $item * @return bool */ protected function userCanSeeMenu($item) { $user = Admin::user(); if (! $user || ! method_exists($user, 'canSeeMenu')) { return true; } return $user->canSeeMenu($item); } /** * 判断权限. * * @param $item * @return bool */ protected function checkPermission($item) { $permissionIds = $item['permission_id'] ?? null; $roles = array_column(Helper::array($item['roles'] ?? []), 'slug'); $permissions = array_column(Helper::array($item['permissions'] ?? []), 'slug'); if (! $permissionIds && ! $roles && ! $permissions) { return true; } $user = Admin::user(); if (! $user || $user->visible($roles)) { return true; } foreach (array_merge(Helper::array($permissionIds), $permissions) as $permission) { if ($user->can($permission)) { return true; } } return false; } /** * @param string $text * @return string */ public function translate($text) { $titleTranslation = 'menu.titles.'.trim(str_replace(' ', '_', strtolower($text))); if (Lang::has($titleTranslation)) { return __($titleTranslation); } return $text; } /** * @param string $uri * @return string */ public function getPath($uri) { return $uri ? (url()->isValidUrl($uri) ? $uri : admin_base_path($uri)) : $uri; } /** * @param string $uri * @return string */ public function getUrl($uri) { return $uri ? admin_url($uri) : $uri; } }注册在/app/Providers/AppServiceProvider.php注册上一步的php文件use App\Admin\Layout\Menu; ... public function register() { //注册菜单列表 $this->app->singleton('admin.menu', Menu::class); }复制模板文件原模板所在位置/vendor/dcat/laravel-admin/resoures/views/partials/menu.blade.php复制到/resoures/views/vendor/admin/partials/menu.blade.php@php $depth = $item['depth'] ?? 0; $horizontal = config('admin.layout.horizontal_menu'); $defaultIcon = config('admin.menu.default_icon', 'feather icon-circle'); @endphp @if($builder->visible($item)) @if(empty($item['children'])) <li class="nav-item"> <a data-id="{{ $item['id'] ?? '' }}" @if(mb_strpos($item['uri'], '://') !== false) target="_blank" @endif href="{{ $builder->getUrl($item['uri']) }}" class="nav-link {!! $builder->isActive($item) ? 'active' : '' !!}"> {!! str_repeat(' ', $depth) !!}<i class="fa fa-fw {{ $item['icon'] ?: $defaultIcon }}"></i> <p> {!! $builder->translate($item['title']) !!} </p> </a> </li> @else <li class="{{ $horizontal ? 'dropdown' : 'has-treeview' }} {{ $depth > 0 ? 'dropdown-submenu' : '' }} nav-item {{ $builder->isActive($item) ? 'menu-open' : '' }}"> <a href="#" data-id="{{ $item['id'] ?? '' }}" class="nav-link {{ $builder->isActive($item) ? ($horizontal ? 'active' : '') : '' }} {{ $horizontal ? 'dropdown-toggle' : '' }}"> {!! str_repeat(' ', $depth) !!}<i class="fa fa-fw {{ $item['icon'] ?: $defaultIcon }}"></i> <p> {!! $builder->translate($item['title']) !!} @if(! $horizontal) <i class="right fa fa-angle-left"></i> @endif </p> </a> <ul class="nav {{ $horizontal ? 'dropdown-menu' : 'nav-treeview' }}"> @foreach($item['children'] as $item) @php $item['depth'] = $depth + 1; @endphp @include('admin::partials.menu', ['item' => $item]) @endforeach </ul> </li> @endif @endif注意:复制出来的文件不一定按着我这个路径存放,只需要在代码关联中引用正确自动加载就能够加载出来。就上述三个文件改动即可,然后具体的数据查询根据业务需求去写即可,可以是在/app/Admin/Layout/Menu.php中 56行后面接着写,也可以将数据查询写到Models中,如果在Models中重写需要在/config/admin.php 中 'menu_model' => Dcat\Admin\Models\Menu::class, 改成自定义的模型位置。总结使用这种定义好的后端框架确实是开发迅速,但是局限性很高,如果有些特殊的需求或者效果还是需要自定义。多翻翻源码还有帮助的。此篇重构dcat菜单列表我觉得还是可以在优化一下的。仅仅记录下解决方法,如果您有更好的方式欢迎告知我。
2023年05月22日
54 阅读
0 评论
1 点赞
2022-09-04
[laravel] 监听方式记录SQL日志
创建监听器php artisan make:listener QueryListener --event=Illuminate\Database\Events\QueryExecuted打开app/Providers/EventServiceProvider.php添加引导protected $listen = [ 'Illuminate\Database\Events\QueryExecuted' => [ 'App\Listeners\QueryListener', ] ];打开app/Listeners/QueryListener#引入log use Illuminate\Support\Facades\Log; #handle方法添加代码: public function handle(QueryExecuted $event) { if (env('APP_DEBUG')) { $sql = str_replace("?", "'%s'", $event->sql); $log = vsprintf($sql, $event->bindings); $log = '[' . date('Y-m-d H:i:s') . '] ' . $log . PHP_EOL; $logDir = storage_path('logs/sql'); // if (!is_dir($logDir)) { // mkdir($logDir, 0777, true); // } file_put_contents($logDir, $log, FILE_APPEND); //Log::channel('sql')->info($log); #未添加sql日志通道 /* 'sql'=>[ 'driver' => 'daily', 'level' => 'debug', 'path' => storage_path('logs/sql/log.log'), ], */ } }补充-添加日志通道在写入日志使用Log::channel('sql')->info($log); 需要配置下日志记录通道在config/logging.php加入以下内容:'sql'=>[ 'driver' => 'daily', 'level' => 'debug', 'path' => storage_path('logs/log.log'), ],
2022年09月04日
101 阅读
0 评论
0 点赞
2022-08-19
[tymon]JWT-AUTO 翻译
[tymon]JWT-AUTO 翻译参考链接:jwt官网 https://jwt-auth.readthedocs.io/en/develop/laravel加载jwt参考 https://learnku.com/laravel/t/27760拉起最新版本:composer require tymon/jwt-auth注意:laravel-5.4版本以下将服务提供者添加到配置文件中的providers数组中config/app.php,如下所示:'providers' => [ ... Tymon\JWTAuth\Providers\LaravelServiceProvider::class, ]发布配置php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"此时自动生成一个config/jwt.php文件,允许配置此包的基础知识。生成密钥php artisan jwt:secret此步会更新.env文件JWT_SECRET={}laravel配置jwt更新用户模型需要在原本的User模型上实现getJWTIdentifier()和 getJWTCustomClaims()<?php namespace App; use Tymon\JWTAuth\Contracts\JWTSubject; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements JWTSubject { use Notifiable; // Rest omitted for brevity /** * Get the identifier that will be stored in the subject claim of the JWT. * * @return mixed */ public function getJWTIdentifier() { return $this->getKey(); } /** * Return a key value array, containing any custom claims to be added to the JWT. * * @return array */ public function getJWTCustomClaims() { return []; } }配置身份验证保护注意此项需要laravel5.2及更高版本是时才有效。在该config/auth.php文件中,您需要进行一些更改来配置 Laravel 以使用jwt防护来支持您的应用程序身份验证。对文件进行下述更改:'defaults' => [ 'guard' => 'api', 'passwords' => 'users', ], ... 'guards' => [ 'api' => [ 'driver' => 'jwt', 'provider' => 'users', ], ],这里我们告诉api守卫使用jwt驱动程序,我们将api守卫设置为默认值。我们现在可以使用 Laravel 内置的 Auth 系统,而 jwt-auth 在幕后工作!添加一些基本的认证路由routes/api.phpRoute::group([ 'middleware' => 'api', 'prefix' => 'auth' ], function ($router) { Route::post('login', 'AuthController@login'); Route::post('logout', 'AuthController@logout'); Route::post('refresh', 'AuthController@refresh'); Route::post('me', 'AuthController@me'); });创建AuthController命令创建php artisan make:controller AuthController添加以下内容<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use App\Http\Controllers\Controller; class AuthController extends Controller { /** * Create a new AuthController instance. * * @return void */ public function __construct() { $this->middleware('auth:api', ['except' => ['login']]); } /** * Get a JWT via given credentials. * * @return \Illuminate\Http\JsonResponse */ public function login() { $credentials = request(['email', 'password']); if (! $token = auth('api')->attempt($credentials)) { return failed('账号或者密码错误'); //return response()->json(['error' => 'Unauthorized'], 401); } $data = array( 'access_token' => $token, 'token_type' => 'bearer', 'expires_in' => auth('api')->factory()->getTTL() * 60 ); return success($data,'登录成功'); //return $this->respondWithToken($token); } /** * Get the authenticated User. * * @return \Illuminate\Http\JsonResponse */ public function me() { return response()->json(auth()->user()); } /** * Log the user out (Invalidate the token). * * @return \Illuminate\Http\JsonResponse */ public function logout() { auth()->logout(); return success([],'已成功注销'); //return response()->json(['message' => 'Successfully logged out']); } /** * Refresh a token. * * @return \Illuminate\Http\JsonResponse */ public function refresh() { return $this->respondWithToken(auth('api')->refresh()); } /** * Get the token array structure. * * @param string $token * * @return \Illuminate\Http\JsonResponse */ protected function respondWithToken($token) { return response()->json([ 'access_token' => $token, 'token_type' => 'bearer', 'expires_in' => auth('api')->factory()->getTTL() * 60 ]); } } 注意上面代码中使用了自动封装的助手函数 success() 和 failed()封装方式详见这篇文章测试最后就可以直接访问一下http://{HOST}/auth/login会得到类似参数:{ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ", "token_type": "bearer", "expires_in": 3600 }验证身份有多种方式通过授权头方式Authorization: Bearer eyJhbGciOiJIUzI1NiI...通过查询字符串参数http://example.dev/me?token=eyJhbGciOiJIUzI1NiI...补充关于测试环境和开发模式切换引发报错Auth guard driver [api] is not defined 尝试使用composer install 或者 composer update补全丢失依赖文件
2022年08月19日
162 阅读
0 评论
0 点赞
2022-07-07
[laravel]自定义辅助函数
[TOC]前言laravel自带的助手函数使用方便。 虽然laravel自带的助手有很多,有的时候也需要自定义那么就需要我们来手动创建比如说接口中常用的方法: 成功返回success(),失败返回failed()经常会使用所以必要的需要封装起来,放在一个起统一管理,前言就几句话还得写的语无伦次,笑了 ::(狗头)创建助手类vim /Helpers/function.php封装<?php /** * @param int $code 返回码 * @param string $message 返回说明 * @param array $data 成功时返回数据 * @param array $errors 失败时返回数据 * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response */ function responseApi(int $code, string $message, array $data = [], array $errors = []) { return response(compact('code', 'message', 'data', 'errors')); } /** * @param array $data 返回数据 * @param string $message 说明 * @param int $code 返回码 * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response */ function success(array $data = [], string $message = 'OK', int $code = 0) { $code = $code == 0 ? $code : -1; return responseApi($code, $message, $data, []); } /* function successWithToken(string $token, string $message = '', array $data = []) { if ($token && !\Illuminate\Support\Str::startsWith($token, 'Bearer ')) { $token = 'Bearer ' . $token; } return success($data, $message)->header(config('auth.token_key'), $token); }*/ /** * @param string $message 说明 * @param int $code 返回码 * @param array $errors 失败时返回数据 * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response */ function failed(string $message = 'Failed', int $code = -1, array $errors = []) { $code = $code == 0 ? -1 : $code; return responseApi($code, $message, [], $errors); } /** * @param string $failMessage 说明 * @param int $statusCode 回状态码 * @param array $errors 错误数据 * @param int $code 返回代码 * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response */ function failedWithStatusCode(string $failMessage = 'Failed', int $statusCode = -1, array $errors = [], int $code = -1) { $statusCode = $statusCode > 400 ? $statusCode : 400; return response(['code' => $code, 'message' => $failMessage, 'data' => [], 'errors' => $errors], $statusCode); } /** * 生成随机字符串(纯字母) * * @param int $length * @return string */ function random_str(int $length): string { return random_in_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", $length); } /** * 生成随机字符串(纯大写字母) * * @param integer $length * @return string */ function random_str_up(int $length): string { return random_in_str("ABCDEFGHIJKLMNOPQRSTUVWXYZ", $length); } /** * 生成随机字符串(纯数字) * * @param int $length * @return string */ function random_number(int $length): string { return random_in_str("0123456789", $length); } /** * 在字符串中随机取字符组成长度为length的字符串 * * @param string $str * @param integer $length * @return string */ function random_in_str(string $str, int $length): string { while (strlen($str) < $length) { $str .= str_shuffle($str); } return substr(str_shuffle($str), mt_rand(0, strlen($str) - $length), $length); } 自动引用如果想让项目可以随时用助手那需要在配置下加载有两种方式。方法一:在composer.json中 添加 autoload中增加"files":["app/Helpers/function.php"]"autoload": { "psr-4": { "App\\": "app/", "Database\\Factories\\": "database/factories/", "Database\\Seeders\\": "database/seeders/" }, "files": [ "app/Helpers/function.php" ] },最后在项目根目录中更新下composercomposer dumpautoload方法二:使用框架自己引导加载在 bootstrap/app.php 中增加require __DIR__ . '/../app/Helpers/function.php';测试最后在随便一个类中可以测试一下return success();
2022年07月07日
159 阅读
0 评论
0 点赞
2022-07-02
[laravel]中间件实现签名鉴权
前言签名是api开发的必不可缺少的一环,实操:一, 创建中间件php文件有两种方法,方法一,是由手动创建 在目录App/Http/Middleware 中创建一个自定义中间件 叫做ApiSgin.php<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use App\Models\Task as TaskModels; class ApiSgin { public function handle(Request $request, Closure $next) { $input = $request->all(); //签名验证具体实现略 //。。。 if ($input['sgin'] != '004e5444e9262496921566aea68784a8') { return failed('签名错误'); //failed自定义封装助手行数 类似 return '{"code":-1,"msg":"error"}'; } //中间件执行代码没有问题想要继续深度执行业务, //使用 $request 调用 $next 回调 return $next($request); } }方法二,使用laravel自带的artisan 工具执行一键创建命令php artisan make:middleware ApiSgin二,设置路由中间件路径可以设置多个地方在App/Http/Kernel.php 中可以填写在protected $middleware = []; //注册全局中间件protected $middlewareGrops=[]; //设置中间件组protected $routeMiddleware = []; //中间件分配给路由/** * The application's route middleware groups. * * @var array<string, array<int, class-string|string>> */ protected $middlewareGroups = [ 'web' => [], 'api' => [], 'sgin' => [ \App\Http\Middleware\ApiSgin::class, ] ]; //或者在路由设置中间映射 /** * The application's route middleware. * * These middleware may be assigned to groups or used individually. * * @var array<string, class-string|string> */ protected $routeMiddleware = [ //sgin签名验证 'sgin'=> \App\Http\Middleware\ApiSgin::class, ];三,路由中注册中间件在 Routes/api.php//需要验证签名 Route::middleware(['sgin'])->group(function () { //.... }有多种设置方式。在laravel手册中介绍的好多种方式,我觉得路由组使用同一个中间件很方便,当然要根据实际业务来使用不同方式的中间件。
2022年07月02日
131 阅读
0 评论
0 点赞
2022-05-19
跨域解决方案
前后端分离项目100%会碰到跨域问题跨域提示Access to XMLHttpRequest at 'http://manage.sdk.phpfunny.cn/index/portal_site/v1/home' from origin 'http://localhost:8080' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.什么是跨域指的是浏览器不能执行其他网站的脚本,它是由浏览器的同源策略造成的,是浏览器对 javascript 施加的安全限制。同源策略:是指协议(protocol)、域名(host)、端口号(port),都必须相同,其中一个不同都会产生跨域。http://www.test.com:8080/ 协议(http)、主域名(test)、子域名(www)、端口号(8080)非同源策略:无法读取非同源网页的cookie、localStorage、IndexedDB无法接触非同源网页的DOM无法向非同源地址发送 AJAX 请求解决跨域方法JSONPCORS 跨域资源共享(Cross-Origin Resource Sharing)反向代理具体解释请看下方实践或者百度网上超多的教程。[前端]nodejs+vue解决跨域采用第三种方案 使用nodejs内置反代来绕过跨域问题详见vue解决跨域文章,还有其他方式等待后期补充。[后端]laravel接口解决跨域利用框架的中间件来允许指定域名请求创建中间件cd Http/Middleware vim EnableCrossRequestMiddleware.php完善中间件内容<?php namespace App\Http\Middleware; use Closure; class EnableCrossRequestMiddleware{ /** * @param $request * @param Closure $next * @return mixed */ public function handle($request, Closure $next) { $response = $next($request); $origin = $request->server('HTTP_ORIGIN') ? $request->server('HTTP_ORIGIN') : ''; $allow_origin = [ 'http://127.0.0.1:8080',//允许访问 'http://manage.sdk.xxxxx.cn',//允许访问 'http://manage.sdk.xxxxx.com/' ]; if (in_array($origin, $allow_origin)) { $response->header('Access-Control-Allow-Origin', $origin); $response->header('Access-Control-Allow-Headers', 'Origin, Content-Type, Cookie, X-CSRF-TOKEN, Accept, Authorization, X-XSRF-TOKEN'); $response->header('Access-Control-Expose-Headers', 'Authorization, authenticated'); $response->header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, OPTIONS'); $response->header('Access-Control-Allow-Credentials', 'true'); } return $response; } }注册中间件在protected $middleware 里写上中间件类名。如果没有Http/Kernel.php则需要创建<?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel extends HttpKernel { /** * The application's global HTTP middleware stack. * * These middleware are run during every request to your application. * * @var array */ protected $middleware = [ \App\Http\Middleware\EnableCrossRequestMiddleware::class, ]; /** * The application's route middleware groups. * * @var array */ protected $middlewareGroups = [ ]; /** * The application's route middleware. * * These middleware may be assigned to groups or used individually. * * @var array */ protected $routeMiddleware = [ ]; } 完成,重新请求即可。其他方式解决跨域PHP项目中共享域设置待补充
2022年05月19日
218 阅读
0 评论
0 点赞
2021-12-31
关于require_once本地资源路径问题
当我们在使用PHP框架的时候,如果框架不支持命名空间,或者某些特殊的情况,我们需要额外的引入文件使用require_once(或者require、include等等)引用相对路径文件时,会提示路径不正确。
2021年12月31日
198 阅读
0 评论
0 点赞
2021-10-25
PHP中常用的两种请求接口方法
GET方式的直接使用$file_contents = file_get_content('http://localhost/operate.php?act=get_user_list&type=json')POST方式得用下面的(需要开启PHP curl支持)。$url = 'http://localhost/operate.php?act=get_user_list&type=json'; $ch = curl_init (); curl_setopt ( $ch, CURLOPT_URL, $url ); curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt ( $ch, CURLOPT_CONNECTTIMEOUT, 10 ); curl_setopt ( $ch, CURLOPT_POST, 1 ); //启用POST提交 $file_contents = curl_exec ( $ch ); curl_close ( $ch );
2021年10月25日
91 阅读
0 评论
0 点赞
2021-10-19
PHP错误和异常处理的学习
错误和异常处理的学习在某些编程语言(例如JAVA)在特定的情况下将自动抛出异常,但是在PHP中异常必须手动抛出。异常处理的概念利用try,Exception,throw写一个简单抛出并捕捉的异常try{ throw new \Exception('发生了不可描述的错误', '500'); }catch(\Exception $e){ echo 'Exception '.$e->getCode().' : '.$e->getMessage().'<br/>'.' in '.$e->getFile().' On Line '.$e->getLine(); }提示109行异常代码就是 throw new \Exception('发生了不可描述的错误', '500');简单解释一下try,Exception,throw一般是try{}代码块和catch(){}代码块配套使用,一个try{}代码块可以配合多个catch代码块捕捉不同类型的异常。有一点需要注意:当有多个catch代码块时,传递给每一个catch代码块的对象必须具有不同的类型,这样php才能找到具体是哪个catch代码块。throw关键字触发异常处理机制。他是一个语言结构而不是函数,所以必须要给他传一个值。throw new \Exception('message', code);这个类的构造函数需要两个参数:一个消息和一个错误代码。Exception类
2021年10月19日
128 阅读
0 评论
0 点赞
2021-06-01
Laravel配合crontab指令创建定时任务
Laravel 配合crontab指令创建定时任务我工作中的项目使用的是Lumen框架,和laravel创建定时任务一样首先要定义调度,也是我们常说的脚本文件在App\Console\Commands下创建Test.php指令创建:php artisan make:command Test手动创建:<?php namespace App\Console\Commands; use Illuminate\Console\Command; class Test extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'test'; /** * The console command description. * * @var string */ protected $description = '测试创建脚本'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return int */ public function handle() { echo '开始执行test脚本'; echo "脚本执行结束"; } } 第二步、编辑 app/Console/Kernel.php 文件,将新生成的类进行注册:protected $commands = [ \App\Console\Commands\Test::class, ];然后就可以直接使用运行脚本指令啦 常用的指令有://查看所有的脚本以及框架自带的一些调度 php artisan list //手动执行指定脚本 php artisan test 参考一下 list指令Laravel Framework 8.41.0 Usage: command [options] [arguments] Options: -h, --help Display help for the given command. When no command is given display help for the list command -q, --quiet Do not output any message -V, --version Display this application version --ansi Force ANSI output --no-ansi Disable ANSI output -n, --no-interaction Do not ask any interactive question --env[=ENV] The environment the command should run under -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug Available commands: clear-compiled Remove the compiled class file db Start a new database CLI session down Put the application into maintenance / demo mode env Display the current framework environment help Display help for a command inspire Display an inspiring quote list List commands migrate Run the database migrations optimize Cache the framework bootstrap files serve Serve the application on the PHP development server test Run the application tests test_cmd 测试创建脚本 tinker Interact with your application up Bring the application out of maintenance mode auth auth:clear-resets Flush expired password reset tokens cache cache:clear Flush the application cache cache:forget Remove an item from the cache cache:table Create a migration for the cache database table config config:cache Create a cache file for faster configuration loading config:clear Remove the configuration cache file db db:seed Seed the database with records db:wipe Drop all tables, views, and types event event:cache Discover and cache the application's events and listeners event:clear Clear all cached events and listeners event:generate Generate the missing events and listeners based on registration event:list List the application's events and listeners key key:generate Set the application key make make:cast Create a new custom Eloquent cast class make:channel Create a new channel class make:command Create a new Artisan command make:component Create a new view component class make:controller Create a new controller class make:event Create a new event class make:exception Create a new custom exception class make:factory Create a new model factory make:job Create a new job class make:listener Create a new event listener class make:mail Create a new email class make:middleware Create a new middleware class make:migration Create a new migration file make:model Create a new Eloquent model class make:notification Create a new notification class make:observer Create a new observer class make:policy Create a new policy class make:provider Create a new service provider class make:request Create a new form request class make:resource Create a new resource make:rule Create a new validation rule make:seeder Create a new seeder class make:test Create a new test class migrate migrate:fresh Drop all tables and re-run all migrations migrate:install Create the migration repository migrate:refresh Reset and re-run all migrations migrate:reset Rollback all database migrations migrate:rollback Rollback the last database migration migrate:status Show the status of each migration notifications notifications:table Create a migration for the notifications table optimize optimize:clear Remove the cached bootstrap files package package:discover Rebuild the cached package manifest queue queue:batches-table Create a migration for the batches database table queue:clear Delete all of the jobs from the specified queue queue:failed List all of the failed queue jobs queue:failed-table Create a migration for the failed queue jobs database table queue:flush Flush all of the failed queue jobs queue:forget Delete a failed queue job queue:listen Listen to a given queue queue:prune-batches Prune stale entries from the batches database queue:restart Restart queue worker daemons after their current job queue:retry Retry a failed queue job queue:retry-batch Retry the failed jobs for a batch queue:table Create a migration for the queue jobs database table queue:work Start processing jobs on the queue as a daemon route route:cache Create a route cache file for faster route registration route:clear Remove the route cache file route:list List all registered routes sail sail:install Install Laravel Sail's default Docker Compose file sail:publish Publish the Laravel Sail Docker files schedule schedule:list List the scheduled commands schedule:run Run the scheduled commands schedule:test Run a scheduled command schedule:work Start the schedule worker schema schema:dump Dump the given database schema session session:table Create a migration for the session database table storage storage:link Create the symbolic links configured for the application stub stub:publish Publish all stubs that are available for customization vendor vendor:publish Publish any publishable assets from vendor packages view view:cache Compile all of the application's Blade templates view:clear Clear all compiled view files要是实现脚本自动定时执行需要配合crontab 指令第三步、创建一个该项目的定时任务* * * * * php /www/blog.phpfunny.cn/artisan schedule:run >> /dev/null 2>&1 //注意:* * * * *分别代表 分 时 日 月 周 (定时任务的时间) /为你的项目位置第四步、指定脚本执行时间(周期)protected function schedule(Schedule $schedule) { $schedule->command('test')//Test.php中的name ->everyFiveMinutes();//每五分钟执行一次 }常用的执行周期:->cron('* * * * *'); 在自定义Cron调度上运行任务 ->everyMinute(); 每分钟运行一次任务 ->everyFiveMinutes(); 每五分钟运行一次任务 ->everyTenMinutes(); 每十分钟运行一次任务 ->everyThirtyMinutes(); 每三十分钟运行一次任务 ->hourly(); 每小时运行一次任务 ->daily(); 每天凌晨零点运行任务 ->dailyAt('13:00'); 每天13:00运行任务 ->twiceDaily(1, 13); 每天1:00 & 13:00运行任务 ->weekly(); 每周运行一次任务 ->monthly(); 每月运行一次任务 ->monthlyOn(4, '15:00'); 每月4号15:00运行一次任务 ->quarterly(); 每个季度运行一次 ->yearly(); 每年运行一次 ->timezone('America/New_York'); 设置时区
2021年06月01日
272 阅读
0 评论
0 点赞
2021-05-30
[PHP基础]使用each+list+while遍历数组
while()+list()+each() 遍历数组要想使用 while()+list()+each() 必须要先搞明白list和each函数的作用。each() 函数的作用:先取得一个数组的‘当前单元’的下标和值(并存放一个数组)然后将指针移到下一个单元。例如:$a = array("bilibili", "youtube", "pornhub", "v2ex"); $arr1 = each($a); $arr2 = each($a); $arr3 = each($a); $arr4 = each($a); echo "<pre>"; print_r ($arr1); echo "</pre>"; echo "<pre>"; print_r ($arr2); echo "</pre>"; echo "<pre>"; print_r ($arr3); echo "</pre>"; echo "<pre>"; print_r ($arr4); echo "</pre>";结果:Array ( [1] => bilibili [value] => bilibili [0] => 0 [key] => 0 ) Array ( [1] => youtube [value] => youtube [0] => 1 [key] => 1 ) Array ( [1] => pornhub [value] => pornhub [0] => 2 [key] => 2 ) Array ( [1] => v2ex [value] => v2ex [0] => 3 [key] => 3 )要注意的是each()函数已自 PHP 7.2.0 起废弃。强烈建议不要使用本函数。list() 的作用:把数组中的值赋给一组变量例如:list($a,$b,$c,$d) = array("bilibili", "youtube", "pornhub", "v2ex"); echo "我最喜欢的视频网站是".$a.',我也经常会去看'. $b.'。<br />程序员网站'.$d.'。<br />'.$c.'只有老司机才会知道。';结果:我最喜欢的视频网站是bilibili,我也经常会去看youtube。 程序员网站v2ex。 pornhub只有老司机才会知道。注意:像 array() 一样,这不是真正的函数,而是语言结构。 list() 可以在单次操作内就为一组变量赋值。在 PHP 7.1.0 之前的版本,list() 仅能用于数字索引的数组,并假定数字索引从 0 开始。PHP 5 里,list() 从最右边的参数开始赋值; PHP 7 里,list() 从最左边的参数开始赋值。如果你用单纯的变量,不用担心这一点。 但是如果你用了具有索引的数组,通常你期望得到的结果和在 list() 中写的一样是从左到右的,但在 PHP 5 里实际上不是, 它是以相反顺序赋值的。通常而言,不建议依赖于操作的顺序,在未来可能会再次发生修改。最后结合使用来遍历数组栗子:<?php $fruit = array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry'); reset($fruit); while (list($key, $val) = each($fruit)) { echo "$key => $val\n"; } ?>结果:a => apple b => banana c => cranberry注意例子中使用了一个reset()函数因为将一个数组赋值给另一个数组时会重置原来的数组指针,因此在上边的例子中如果我们在循环内部将 $fruit 赋给了另一个变量的话将会导致无限循环。
2021年05月30日
244 阅读
0 评论
2 点赞
2020-08-16
PHP项目中共享域设置
在初始化initialize中写入头信息当无需ajax使用jsonp的时候,可以在初始化initialize下写入头信息,请求源,请求方式的方法解决跨域受同源策略阻拦的问题,注意localhost和127.0.0.1也属于跨域//允许跨域的域名,*代表所有域名都可以访问,可以换成域名,并且多个域名用逗号分割开。 header('Access-Control-Allow-Origin:*'); //请求头中设置允许的请求方法 header('Access-Control-Allow-Headers:X-Requested-With,X_Requested_With,Token,Client,Content-Type,Accept'); //响应标头指定响应访问所述资源到时允许的一种或多种方法预检请求。 header('Access-Control-Allow-Methods:GET,POST,PUT,DELETE');X-Requested-With ,请求头 区分ajax请求还是普通请求可以看到 Ajax 请求多了个 x-requested-with ,可以利用它,request.getHeader(“x-requested-with”); 为 null,则为传统同步请求,为 XMLHttpRequest,则为 Ajax 异步请求。Token(令牌),Client(客户机),Content-Type(在请求中(如POST或PUT),客户端告诉服务器实际发送的数据类型)Accept一般配合input标签使用在文件上传中使用 accept 属性,本例中的输入字段可以接受 GIF 和 JPEG 两种图像:<form> <input type="file" name="pic" id="pic" accept="image/gif, image/jpeg" /> </form>如果不限制图像的格式,可以写为:accept="image/*"。什么是Access-Control-Allow-Origin他是HTML5中定义的一种解决资源跨域的策略。通过服务器端返回带有Access-Control-Allow-Origin标识的Response header,用来解决资源的跨域权限问题。html设置方式:<meta http-equiv="Access-Control-Allow-Origin" content="*">Access-Control-Allow-Origin:*的安全性根据w3c标准,如果b.com域下js要读取到a.com域下的需要登录才能访问的资源,需要a.com域同时设置了 Access-Control-Allow-Credentials: true头(即允许third-party cookie)并且如果设置access-control-allow-origin为*星号(任何域),则Access-Control-Allow-Credentials头是不能设置为true的,参见http://www.w3.org/TR/cors/#resource-requests所以理论上网站设置了Access-control-allow-origin: *,并没有实际危害,因为并不能跨域读取私密数据(登录后才可见数据)(在重复说一下显示重要性)发现许多网站会根据请求头中的Origin值然后设置Access-control-allow-origin,且同时设置了Access-Control-Allow-Credentials为true,导致可以被黑客利用Access-control-allow-origin:null 是可以携带cookie的。也存在特定场景下不需要cookie也能攻击的:基于ip认证的资源跨域读取缓存投毒,增加Vary: Origin http头可以避免使用php函数实现跨域读取资源file_get_contents() 把整个文件读入一个字符串中。语法:file_get_contents(path,include_path,context,start,max_length)参数描述path必需。规定要读取的文件。include_path可选。如果您还想在 include_path(在 php.ini 中)中搜索文件的话,请设置该参数为 '1'。context可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。若使用 NULL,则忽略。start可选。规定在文件中开始读取的位置。该参数是 PHP 5.1 中新增的。max_length可选。规定读取的字节数。该参数是 PHP 5.1 中新增的。不建议使用,使用这个函数会将资源加载到服务器内存,资源如果过大可能会导致系统假死,宕机情况的发生。最后说一下跨域最好还是使用jsonp来处理,待补充
2020年08月16日
221 阅读
0 评论
0 点赞
1
2
3