Laravel8 Sanctum API认证+Vue问卷 搭建前后端分离SPA应用

本博客详细介绍了如何使用Laravel8的Sanctum扩展进行API认证,并结合Vue.js构建一个前后端分离的SPA应用,涉及到Sanctum的安装、配置、跨域访问设置,以及问卷API框架的实现,包括数据模型、控制器和路由。前端部分涵盖了Vue项目的创建、登录视图和脚本。整个过程旨在实现安全的API访问和问卷数据的交互。

1 Sanctum 扩展安装与配置

我们使用Sanctum 的身份验证功能为Vue前端提供API验证支持。
SPA 与 API 必须共享同一个顶级域名,但可以被放置在不同的子域名上,本项目前后端在同一顶级域名的两个子域。

  • WNMP环境

phpstudy 8.1

  • 项目目录
    命令行工具建议使用windows PowerShell,比cmd更强大,兼容cmd的DOS命令集
PS D:\web_www> dir

    目录: D:\web_www


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2022-03-12     18:44                api.laravel
d-----       2022-03-27      7:29                demand.vue

PS D:\web_www>

api.laravel 后端laravel项目目录
demand.vue 前端Vue问卷项目目录

  • 前端

本地虚拟域名 demand.my.domain 或 127.0.0.1:8080

  • 后端

本地虚拟域名 api.my.domain 或 127.0.0.1:8000

  • laravel站点需要设置伪静态,在phpstudy网站->管理->伪静态中填写
    try_files $uri u r i / / i n d e x . p h p ? uri/ /index.php? uri//index.php?query_string;

在这里插入图片描述

1.1 安装Sanctum

  • 安装
    在laravel项目目录安装sanctum
    composer require laravel/sanctum
  • 发布 Sanctum 的配置和迁移文件
    php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
  • 数据迁移
    php artisan migrate
PS D:\web_www\api.laravel>php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (34.38ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (29.99ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (28.26ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated:  2019_12_14_000001_create_personal_access_tokens_table (54.88ms)

personal_access_tokens 表用于存放Api令牌

1.2 配置API中间件

将 Sanctum 的中间件添加到你应用的 app/Http/Kernel.php 文件中的 api 中间件组中,使api路由能够调用Sanctum进行身份验证

app/Http/Kernel.php

'api' => [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    'throttle:api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

1.3 跨域访问配置

1.3.1 配置Sanctum跨域认证请求

如果本地开发使用VUE的127.0.0.1:8080的 URL 访问API,则应确保在域中包含8080端口号

config/sanctum.php

	/*
    |--------------------------------------------------------------------------
    | Stateful Domains
    |--------------------------------------------------------------------------
    |
    | Requests from the following domains / hosts will receive stateful API
    | authentication cookies. Typically, these should include your local
    | and production domains which access your API via a frontend SPA.
    |
    */

    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        Sanctum::currentApplicationUrlWithPort()
    ))),

Stateful的配置首选从env环境中提取参数,多个域名用逗号分隔,那我们就不修改这个配置文件,直接修改.env

SANCTUM_STATEFUL_DOMAINS = 127.0.0.1:8080

未设置SANCTUM_STATEFUL_DOMAINS,可能出现的报错信息

Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/login' from origin 'http://127.0.0.1:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

我们在phpstudy中设置了虚拟域名demand.my.domain

SANCTUM_STATEFUL_DOMAINS = demand.my.domain

可能出现的报错

Access to XMLHttpRequest at 'http://api.my.domain/sanctum/csrf-cookie' from origin 'http://demand.my.domain' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
  • 解决办法:输入完整域名
SANCTUM_STATEFUL_DOMAINS = http://demand.my.domain

1.3.2 配置Laravel跨域访问

config/cors.php

	'paths' => ['api/*', 'sanctum/csrf-cookie'],
	// 配置跨域支持的请求方式
    'allowed_methods' => ['*'],
	// 配置允许跨域访问的源,*表示全部允许
    'allowed_origins' => ['*'],
	// 正则匹配允许跨域访问的源
    'allowed_origins_patterns' => [],
	// 配置允许跨域的请求头
    'allowed_headers' => ['*'],
	// 自定义请求响应的Head信息
    'exposed_headers' => [],
	// 预检请求的有效时长
    'max_age' => 0,
	// 是否允许请求发送cookie
    'supports_credentials' => true,
  • 允许跨域的路由
    ‘paths’ => [‘api/*’, ‘sanctum/csrf-cookie’],
  • 允许发起的Http请求中带有验证凭证
    ‘supports_credentials’ => true,

1.3.3 配置Cookie会话域

支持同根域下的任何子域,如my.com根域名下自定义解析的www.my.com、spa.my.com、wj.my.com,这些子域名都能保持正常Cookie会话

config/session.php

	/*
    |--------------------------------------------------------------------------
    | Session Cookie Domain
    |--------------------------------------------------------------------------
    |
    | Here you may change the domain of the cookie used to identify a session
    | in your application. This will determine which domains the cookie is
    | available to in your application. A sensible default has been set.
    |
    */

    'domain' => env('SESSION_DOMAIN', null),

session配置文件的domain使用环境变量值,我们可以直接在环境量中配置:

.env

SESSION_DOMAIN=.my.domain

2 问卷API框架

2.1 数据模型

2.1.1 用户模型

修改Laravel已经存在的用户模型app\Models\User.php

引入并使用Sanctum API 令牌验证模块HasApiTokens

use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
   
   
    use HasApiTokens, HasFactory, Notifiable;
}
	/**
     * The attributes that are mass assignable.
     * 可批量填充的字段
     * @var array
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     * 模型转换为数组时应当隐藏的字段
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     * 数据库取出的字段属性转换成需要的数据类型
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

2.1.2 用户数据填充

修改用户数据工厂数据填充规则,修改默认用户密码 “my123456”

database\factories\UserFactory.php

		return [
            'name' => $this->faker->name,
            'email' => $this->faker->unique()->safeEmail,
            'email_verified_at' => now(),
            'password' => bcrypt('my123456'),
            //'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'remember_token' => Str::random(10),
        ];

设置自动生成10个用户(一般默认就是10)

database\seeders\DatabaseSeeder.php

		\App\Models\User::factory(10)->create();

2.1.3 问卷题目模型

  • 创建问卷模型、迁移文件、控制器

-m 自动创建迁移文件
-c 自动创建控制器

模型命名用单数,创建的数据表自动命名为复数
php artisan make:model Question -m -c

PS D:\web_www\api.laravel> php artisan make:model Question -m -c
Model created successfully.
Created Migration: 2022_03_27_081309_create_questions_table
Controller created successfully.
  • 增加字段
    修改迁移文件,增加题目内容数据字段[content]
  • <
以下是使用Laravel 8Sanctum扩展进行API认证,并结合Vue.js构建前后端分离SPA应用的详细步骤: ### 1. Sanctum的安装与配置 - **安装Sanctum**:在Laravel项目的根目录下,通过Composer安装Laravel Sanctum扩展包。 ```bash composer require laravel/sanctum ``` - **发布配置和迁移文件**:运行以下命令发布Sanctum的配置文件和迁移文件。 ```bash php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider" ``` - **运行迁移**:执行迁移命令,在数据库中创建必要的表。 ```bash php artisan migrate ``` - **配置 `Kernel.php`**:在 `app/Http/Kernel.php` 文件中,将 `Sanctum` 的中间件添加到 `api` 中间件组。 ```php 'api' => [ \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ``` ### 2. 跨域访问设置 - **安装 `fruitcake/laravel-cors`**:为了处理跨域请求,安装 `fruitcake/laravel-cors` 包。 ```bash composer require fruitcake/laravel-cors ``` - **配置 `cors.php`**:在 `config/cors.php` 文件中,配置允许的来源、请求方法等。确保允许你的Vue应用的域名。 ```php 'allowed_origins' => ['http://your-vue-app.com'], ``` ### 3. 问卷API框架的实现 #### 数据模型 - **创建问卷模型**:使用Artisan命令创建问卷模型和迁移文件。 ```bash php artisan make:model Questionnaire -m ``` - **定义迁移文件**:在生成的迁移文件中,定义问卷表的结构。 ```php Schema::create('questionnaires', function (Blueprint $table) { $table->id(); $table->string('title'); $table->text('description')->nullable(); $table->timestamps(); }); ``` - **运行迁移**:执行迁移命令,创建问卷表。 ```bash php artisan migrate ``` #### 控制器 - **创建问卷控制器**:使用Artisan命令创建问卷控制器。 ```bash php artisan make:controller QuestionnaireController ``` - **编写控制器方法**:在 `QuestionnaireController` 中编写处理问卷数据的方法。 ```php <?php namespace App\Http\Controllers; use App\Models\Questionnaire; use Illuminate\Http\Request; class QuestionnaireController extends Controller { public function index() { return Questionnaire::all(); } public function store(Request $request) { return Questionnaire::create($request->all()); } public function show(Questionnaire $questionnaire) { return $questionnaire; } public function update(Request $request, Questionnaire $questionnaire) { $questionnaire->update($request->all()); return $questionnaire; } public function destroy(Questionnaire $questionnaire) { $questionnaire->delete(); return response()->json(null, 204); } } ``` #### 路由 - **定义API路由**:在 `routes/api.php` 文件中定义问卷相关的路由。 ```php use App\Http\Controllers\QuestionnaireController; Route::middleware('auth:sanctum')->group(function () { Route::apiResource('questionnaires', QuestionnaireController::class); }); ``` ### 4. Vue项目创建 - **创建Vue项目**:使用Vue CLI创建一个新的Vue项目。 ```bash vue create my-vue-app cd my-vue-app ``` - **安装axios**:安装 `axios` 用于发送HTTP请求。 ```bash npm install axios ``` ### 5. 登录视图和脚本编写 #### 登录视图 - **创建登录组件**:在 `src/components` 目录下创建 `Login.vue` 组件。 ```vue <template> <div> <h1>Login</h1> <input v-model="email" placeholder="Email" /> <input v-model="password" type="password" placeholder="Password" /> <button @click="login">Login</button> </div> </template> <script> import axios from 'axios'; export default { data() { return { email: '', password: '', }; }, methods: { async login() { try { const response = await axios.post('http://your-laravel-api.com/api/login', { email: this.email, password: this.password, }); localStorage.setItem('token', response.data.token); this.$router.push('/questionnaires'); } catch (error) { console.error(error); } }, }, }; </script> ``` #### 问卷视图 - **创建问卷列表组件**:在 `src/components` 目录下创建 `QuestionnaireList.vue` 组件。 ```vue <template> <div> <h1>Questionnaires</h1> <ul> <li v-for="questionnaire in questionnaires" :key="questionnaire.id"> {{ questionnaire.title }} </li> </ul> </div> </template> <script> import axios from 'axios'; export default { data() { return { questionnaires: [], }; }, async mounted() { try { const token = localStorage.getItem('token'); const response = await axios.get('http://your-laravel-api.com/api/questionnaires', { headers: { Authorization: `Bearer ${token}`, }, }); this.questionnaires = response.data; } catch (error) { console.error(error); } }, }; </script> ``` #### 路由配置 - **配置路由**:在 `src/router/index.js` 文件中配置路由。 ```javascript import Vue from 'vue'; import VueRouter from 'vue-router'; import Login from '../components/Login.vue'; import QuestionnaireList from '../components/QuestionnaireList.vue'; Vue.use(VueRouter); const routes = [ { path: '/login', name: 'Login', component: Login, }, { path: '/questionnaires', name: 'QuestionnaireList', component: QuestionnaireList, meta: { requiresAuth: true }, }, ]; const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes, }); router.beforeEach((to, from, next) => { const isAuthenticated = localStorage.getItem('token'); if (to.matched.some(record => record.meta.requiresAuth) && !isAuthenticated) { next('/login'); } else { next(); } }); export default router; ``` ### 6. 运行项目 - **启动Laravel服务**:在Laravel项目根目录下,启动Laravel服务。 ```bash php artisan serve ``` - **启动Vue项目**:在Vue项目根目录下,启动Vue开发服务器。 ```bash npm run serve ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值