记 Laravel Sanctum 实现 token登录

发布时间 2023-10-04 12:01:26作者: cccht

记 Laravel Sanctum 实现 token登录

  1. 假设已经安装好 Laravel

  2. 安装 Laravel Sanctum.

    composer require laravel/sanctum
    
    php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
    
    php artisan migrate
    
  3. 修改 ../app/Http/Kernel.php

    use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
    
    ...
    
        protected $middlewareGroups = [
            ...
    
            'api' => [
                EnsureFrontendRequestsAreStateful::class,
                'throttle:60,1',
                \Illuminate\Routing\Middleware\SubstituteBindings::class,
            ],
        ];
    
        ...
    ],
    
  4. 修改 ../app/User.php

    use Laravel\Sanctum\HasApiTokens;
    
    class User extends Authenticatable
    {
        use HasApiTokens, Notifiable;
    }
    
  5. 创建用户

    php artisan make:seeder UsersTableSeeder
    
    DB::table('users')->insert([
        'name' => 'John Doe',
        'email' => 'john@doe.com',
        'password' => Hash::make('password')
    ]);
    // into the run() function in database/seeds/UsersTableSeeder.php
    
    
    // To seed users table with user, let's run:
    php artisan db:seed --class=UsersTableSeeder
    
  6. routes/api.php 创建 路由 /login

    // ../routes/api.php
    
    use App\User;
    use Illuminate\Support\Facades\Hash;
    
    Route::post('/login', function (Request $request) {
        $data = $request->validate([
            'email' => 'required|email',
            'password' => 'required'
        ]);
    
        $user = User::where('email', $request->email)->first();
    
        if (!$user || !Hash::check($request->password, $user->password)) {
            return response([
                'message' => ['These credentials do not match our records.']
            ], 404);
        }
    
        $token = $user->createToken('my-app-token')->plainTextToken;
    
        $response = [
            'user' => $user,
            'token' => $token
        ];
    
        return response($response, 201);
    });
    
  7. /routes/api.php 文件中把 auth:api 替换成 auth:sanctum

    // ../routes/api.php
    
    Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
        return $request->user();
    });
    
  8. 修改 CORS 跨域

    // ../config/cors.php
    
        'paths' => ['api/*', 'login', 'logout'],
    
        'allowed_methods' => ['*'],
    
        'allowed_origins' => ['*'],
    
        'allowed_origins_patterns' => [],
    
        'allowed_headers' => ['*'],
    
        'exposed_headers' => [],
    
        'max_age' => 0,
    
        'supports_credentials' => true,
    
    
    // .env 文件
    SANCTUM_STATEFUL_DOMAINS=127.0.0.1
    
  9. Vue 请求时加上 Authorization

    // route/index.js
    import { createRouter, createWebHashHistory } from "vue-router"
    import store from '../store.ts'
    
    const routes = [
        {
            path: '/',
            component: () => import('@/components/AdminIndex.vue')
        },{
            path: '/admin',
            component: () => import('@/components/AdminIndex.vue')
        },{
            path: '/login',
            component: () => import('@/components/AdminLogin.vue')
        },
    ]
    if (sessionStorage.getItem("token")){
        store.commit("set_token", sessionStorage.getItem("token"))
    }
    
    export const router = createRouter({
        history: createWebHashHistory(),
        routes: routes
    })
    
    export default router
    
    
    // store.ts
    import { createStore } from 'vuex';
    
    export default createStore({
        state: {
            token: ''
        },
        getters: {},
        mutations: {
            set_token(state, token) {
                state.token = token;
                sessionStorage.token = token
            }
        },
        actions: {},
        modules: {}
    });
    
    // main.js
    import { createApp } from 'vue'
    import App from './App.vue'
    import Antd from 'ant-design-vue';
    import router from './router/index'
    import VueCookies from 'vue3-cookies'
    import store from './store.ts'
    
    // import 'ant-design-vue/dist/antd.css';
    import VueLazyload from 'vue-lazyload'
    import axios from "axios";
    
    // 添加请求拦截器
    axios.interceptors.request.use(function (config) {
        // 在发送请求前的操作
        // 判断是否存在token,如果存在将每个页面header添加token
        if (store.state.token) {
            console.log(store.state.token)
            // config.headers.common['Authorization'] = "Bearer " + store.state.token
            config.headers.Authorization = "Bearer " + store.state.token
    
        }
        return config
    }, function (error) {
        router.push('/')
        return Promise.reject(error)
    })
    // 添加响应拦截器
    axios.interceptors.response.use(function (response) {
        // 操作相应数据
        return response
    }, function (error) {
        // 响应错误后做什么(可自由发挥)
        if (error.response) {
            switch (error.response.status) {
                case 401:
                    store.commit('del_token')
                    router.push('/')
            }
        }
        return Promise.reject(error)
    })
    
    
    const app = createApp(App);  // 创建App
    app.use(VueLazyload)
    app.use(router)
    app.use(store)
    app.use(VueCookies)
    app.use(Antd).mount('#app');
    
    // AdminIndex.vue
    <script setup>
    	const store = useStore();
    	const {proxy} = getCurrentInstance()
    	const loginAdmin = (data) => {
        console.log(data)
        if (data['status']==="success") {
            message.success('登录成功!');
            // 设置cookie
            store.commit("set_token", data['token']['plainTextToken']);
            // get_data()
            loginCheck.value = "true"
            // 'plainTextToken'
        }
        else {
            message.error('登录失败,请检查账号密码重试');
        }
    }
    </script>
    

参考地址:https://dev.to/romanpaprotsky/vue-js-tok...

译文地址:https://learnku.com/laravel/t/43077