Laravel 中如何实现设备认证?

Laravel 中实现设备认证的几种方法

在物联网系统中,设备认证是确保安全通信的关键环节。以下是几种在 Laravel 中实现设备认证的方法:

1. API Token 认证 (简单方案)

创建设备时生成 Token

// 在 Device 模型中
use Illuminate\Support\Str;

public static function boot()
{
    parent::boot();
    
    static::creating(function ($device) {
        $device->api_token = Str::random(60);
    });
}

验证中间件

php artisan make:middleware AuthenticateDevice
namespace App\Http\Middleware;

use Closure;
use App\Models\Device;

class AuthenticateDevice
{
    public function handle($request, Closure $next)
    {
        $token = $request->bearerToken() ?? $request->input('api_token');
        
        if (!$token || !Device::where('api_token', $token)->exists()) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }
        
        return $next($request);
    }
}

注册中间件

app/Http/Kernel.php 中:

protected $routeMiddleware = [
    // ...
    'device.auth' => \App\Http\Middleware\AuthenticateDevice::class,
];

使用中间件保护路由

Route::middleware('device.auth')->group(function () {
    Route::post('/update', [DeviceController::class, 'update']);
    // 其他需要认证的路由
});

2. Laravel Sanctum (推荐方案)

安装 Sanctum

composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate

配置设备模型

use Laravel\Sanctum\HasApiTokens;

class Device extends Model
{
    use HasApiTokens;
    
    // ...
}

创建设备并生成 Token

public function register(Request $request)
{
    $device = Device::create($request->validated());
    $token = $device->createToken('device-token')->plainTextToken;
    
    return response()->json([
        'device' => $device,
        'token' => $token
    ]);
}

认证请求

设备需要在请求头中添加:

Authorization: Bearer {token}

3. JWT 认证 (适合分布式系统)

安装 jwt-auth

composer require tymon/jwt-auth
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
php artisan jwt:secret

配置设备模型

use Tymon\JWTAuth\Contracts\JWTSubject;

class Device extends Model implements JWTSubject
{
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }
    
    public function getJWTCustomClaims()
    {
        return [];
    }
}

创建认证控制器

use Tymon\JWTAuth\Facades\JWTAuth;

class DeviceAuthController extends Controller
{
    public function login(Request $request)
    {
        $credentials = $request->only('device_id', 'password');
        
        if (!$token = JWTAuth::attempt($credentials)) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }
        
        return response()->json([
            'access_token' => $token,
            'token_type' => 'bearer',
            'expires_in' => auth()->factory()->getTTL() * 60
        ]);
    }
}

保护路由

Route::middleware('auth:api')->group(function () {
    // 需要认证的路由
});

4. 双向SSL认证 (高安全性要求)

生成证书

# 生成CA证书
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 365 -key ca.key -out ca.crt

# 生成设备证书
openssl genrsa -out device.key 2048
openssl req -new -key device.key -out device.csr
openssl x509 -req -days 365 -in device.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out device.crt

Laravel 配置

config/nginx/ssl.conf 中添加:

ssl_client_certificate /path/to/ca.crt;
ssl_verify_client on;

中间件验证

public function handle($request, Closure $next)
{
    if (!$request->hasValidSignature()) {
        abort(401, 'Invalid client certificate');
    }
    
    $certificate = $request->server('SSL_CLIENT_CERT');
    $deviceId = $this->extractDeviceIdFromCert($certificate);
    
    if (!Device::where('id', $deviceId)->exists()) {
        abort(403, 'Device not registered');
    }
    
    return $next($request);
}

最佳实践建议

  1. 短期令牌:对于高安全要求的系统,使用短期有效的JWT或OAuth令牌
  2. 设备指纹:结合设备唯一标识(如MAC地址)进行双重验证
  3. 速率限制:防止暴力破解
    Route::middleware(['throttle:10,1'])->group(...);
    
  4. 令牌刷新:实现令牌刷新机制,避免长期使用同一令牌
  5. 日志记录:记录所有设备认证尝试,便于安全审计

选择哪种方案取决于你的具体需求:

  • 简单项目:API Token 或 Sanctum
  • 分布式系统:JWT
  • 高安全性要求:双向SSL + 令牌认证
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值