Debian+Nginx+PHP HTTPS配置模板

Nginx+PHP+HTTPS的配置模板,如果要部署其它网站,可以基于此进行修改:

# 处理 HTTP 请求,所有请求都重定向到 https://notes.wujie.me
server {
    listen 80;
    server_name notes.wujie.me notes.wujie.me;  # 同时匹配带 www 和不带 www 的域名

    # 所有请求都重定向到 https://notes.wujie.me
    return 301 https://notes.wujie.me$request_uri;
}

# 处理不带 www 的 HTTPS 请求,重定向到带 www 的域名
server {
    listen 443 ssl http2;
    server_name notes.wujie.me;  # 不带 www 的域名

    ssl_certificate /etc/nginx/ssl/notes.wujie.me.pem;  # 证书路径
    ssl_certificate_key /etc/nginx/ssl/notes.wujie.me.key;  # 证书路径

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
    ssl_ecdh_curve secp384r1;
    ssl_session_timeout 10m;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on;

    # 重定向所有不带 www 的 HTTPS 请求到 notes.wujie.me
    return 301 https://notes.wujie.me$request_uri;
}

# 处理带 www 的 HTTPS 请求
server {
    listen 443 ssl http2;
    root /var/www/notes.wujie.me; # 确保这里是正确的根目录路径
    index index.html index.htm index.php index.nginx-debian.html;

    server_name  notes.wujie.me;
    client_max_body_size 20m;

    ssl_certificate /etc/nginx/ssl/notes.wujie.me.pem; # 确保证书路径正确
    ssl_certificate_key /etc/nginx/ssl/notes.wujie.me.key; # 确保证书路径正确

    #加上TLSv1,HTTPS检测会报PCI DSS不合规
    ssl_protocols  TLSv1.2 TLSv1.3;# Requires nginx >= 1.13.0 else use TLSv1.2
    ssl_prefer_server_ciphers on;
    ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
    ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
    ssl_session_timeout 10m;
    ssl_session_cache shared:SSL:10m;
    ssl_session_tickets off; # Requires nginx >= 1.5.9
    ssl_stapling on; # Requires nginx >= 1.3.7
    ssl_stapling_verify on; # Requires nginx => 1.3.7

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
}

Debian+Nginx+PHP配置模板

Nginx+PHP+HTTP的配置模板,如果要部署其它网站,可以基于此进行修改:

server {
    listen 80;
    root /var/www/www.example.com;
    # Add index.php to the list if you are using PHP
    index index.html index.htm index.php index.nginx-debian.html;

    server_name www.example.com example.com;

    client_max_body_size 20m;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;

        # With php-fpm (or other unix sockets):
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }
}

Debian配置系统时区

默认的Debian时区一般是UTC(协调世界时),我们在使用时,往往需要对时区进行修改,以方便使用。修改Debian时区,可以使用下面的命令:

dpkg-reconfigure tzdata

运行后,会出来一个列表,此时我们可以根据需要选择,很简单。

dpkg-reconfigure tzdata 是一个用于重新配置系统时区的命令。

在基于 Debian 的 Linux 系统(如 Ubuntu)中,tzdata 是一个提供时区信息的软件包。通过运行 dpkg-reconfigure tzdata,你可以重新设置系统的时区,以确保系统显示的时间是正确的。

设置完成后,命令会显示类似以下的信息:

Current default time zone: 'Asia/Shanghai'
Local time is now:      Fri Nov 29 18:45:00 CST 2024
Universal Time is now:  Fri Nov 29 10:45:00 UTC 2024

可以执行date命令以查看当前时间。

Laravel上线一定要优化的两个配置

1、缓存配置信息:php artisan config:cache

该操作把配置信息从.env缓存到php文件中,否则会因为高并发,多个请求同时读取.env文件,会造成读取失败,从而读取到了config文件夹下的默认配置信息,会造成数据库连接失败,或读取不到 APPP_KEY 等错误。

2、打开opcache,这个真的会有很大的性能提升!执行 vi /etc/php/8.3/fpm/php.ini,注意不同服务器上的版本和路径。

具体修改地方如下图:

去掉zend_extension前面的注释

设置opcache.enable=1

Laravel用户登录

Laravel中做登录,真的太简单了,框架已经集成了大多数的功能,我们只需要把相关数据传递过去即可。代码如下:

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    public function index()
    {
        // 如果用户已登录,则直接跳转到之前页面
        if (Auth::check()) {    
            return redirect(url()->previous());
        }
      
        return view('login');
    }

    public function login(Request $request)
    {
        $credentials = $request->validate([
            'username' => ['required'],
            'password' => ['required'],
        ]);
 
        if (Auth::attempt($credentials, $request->remember)) {
            $request->session()->regenerate(); 
            return redirect()->intended();
        }
 
        return back()->withErrors([
            'loginError' => '用户名或密码不正确。',
        ])->onlyInput('username');
    }

    public function logout(Request $request)
    {
        Auth::logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();
        return redirect('/')->with('success', '退出成功!');
    }
}

相应的路由如下:

Route::get('/login', [LoginController::class, 'index'])->name('login.index');
Route::post('/login', [LoginController::class, 'login'])->name('login');
Route::get('/logout', [LoginController::class, 'logout'])->middleware('auth')->name('logout');

Laravel在FormRequest验证中返回JSON

Laravel中表单验证可以用FormRequest来进行,但是这个默认是返回视图文件的,如果想要把验证结果以JSON格式返回,可以使用如下代码(failedValidation函数):

<?php

namespace App\Http\Requests;

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpFoundation\Response;

class TagStoreRequest extends FormRequest
{
    
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, mixed>
     */
    public function rules(): array
    {
        return [
            'tag' => 'required|unique:tags',
        ];
    }

    public function messages(): array
    {
        return [
            'tag.required'=> '标签名称不能为空!',
            'rag.unique' => '该标签已存在!',
        ];
    }

    protected function failedValidation(Validator $validator)
    {
        throw new ValidationException(
            $validator,
            response()->json(
                [
                    'code'=>-1,
                    'msg'=> $validator->errors()->first()
                ],
                Response::HTTP_UNPROCESSABLE_ENTITY
            )
        );       
    }
}

Laravel更新时的唯一性验证

在执行update进行更新数据时,有时需要对唯一性进行验证,这时要在验证项的后面加上一个ID,不然Laravel会认为该字段内容已存在。

具体验证代码如下:

$validator = validator($request->all(), [
    'name' => 'required|unique:departments,name,' . $department->id,
]);

if ($validator->fails()) {
    return response()->json([
        'code' => -1,
        'msg' => $validator->errors()->first()
    ])->setEncodingOptions(JSON_UNESCAPED_UNICODE);
}

$department->update($validator->valid());
return response()->json(['code' => 0, 'msg' => 'success']);

Laravel表单验证返回JSON

新增时的验证:

$validator = validator($request->all(), [
    'name' => 'required|unique:departments',
]);

if ($validator->fails()) {
    return response()->json([
        'code'=>-1,
        'msg'=> $validator->errors()->first()
    ])->setEncodingOptions(JSON_UNESCAPED_UNICODE);
}

Department::create($validator->valid());
return response()->json(['code'=>0]);

获取已验证的数据:$validator->valid()

Laravel使用laravel-permission进行权限管理

安装

composer require spatie/laravel-permission

发布迁移文件:

php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="migrations"

在config/app.php 中,Providers 数组里添加:

'providers' => [
    // ...
    Spatie\Permission\PermissionServiceProvider::class,
];

发布配置文件:

php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="config"

迁移数据库

php artisan migrate

在User Model 引用 HasRoles trait:

use Spatie\Permission\Models\Role;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable, HasRoles;
}

用法:

创建角色:$role=Role::create(['name'=>'超级管理员']);

创建权限:$permission=Permission::create(['name'=>'*']);

给角色赋予权限:$role->givePermissionTo($permission);

给用户一个角色:$user->assignRole('超级管理员');

在blade页面获取用户的第一个角色:{{ Auth()->user()->getRoleNames()->first() }}