繁体   English   中英

使用 laravel + vue sanctum 保护路由

[英]use laravel + vue sanctum to protect Route

我正在使用 laravel + vue sanctum,我安装了 sanctum,我尝试隐藏非注册用户的文章并仅向已登录的用户显示它们,但在任何一种情况下文章都不会出现,并且出现此消息在控制台中:

 app.js:197 GET http://localhost:8000/api/articles/ 401 (Unauthorized)
app.js:607 Uncaught (in promise) Error: Request failed with status code 401
    at createError (app.js:607)
    at settle (app.js:878)
    at XMLHttpRequest.handleLoad (app.js:82)

我的 api.php 文件是:

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});

Route::group(['middleware' => ['auth:sanctum']], function () {
      Route::resource('articles', ArticleController::class);
});

我的登录文件是:

 <template>
    <div>
        <div class="container">
            <div class="row d-flex justify-content-center">
                <div class="col-6">
                <form class="form-signin">
                    <h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>

                    <label for="inputEmail" class="sr-only">Email address</label>
                    <span class="text-danger" v-if="errors.email">{{errors.email[0]}}</span>
                    <input type="email" id="inputEmail" class="form-control" placeholder="Email address" required autofocus v-model="form.email">

                    <label for="inputPassword" class="sr-only">Password</label>
                    <span class="text-danger" v-if="errors.password">{{errors.password[0]}}</span>
                    <input type="password" id="inputPassword" class="form-control" placeholder="Password" required v-model="form.password">

                    <div class="checkbox mb-3">
                        <label>
                        <input type="checkbox" value="remember-me"> Remember me
                        </label>
                    </div>

                    <button @click.prevent="loginUser" class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>

                    <p class="mt-5 mb-3 text-muted">&copy; 2017-2018</p>
                </form>
                </div>
            </div>
        </div>
    </div>
</template>

    <script>
    export default {
        data(){
            return{
                form:{
                    email: '',
                    password: '',
                    device_name: 'test'
                },
                errors: []
            }
        },
        methods:{
             loginUser(){
                 axios.post('/api/login', this.form).then(() =>{
                    this.$router.push({ name: 'MainPage' })
                 }).catch((error) =>{
             this.errors = error.response.data.errors;
                })
             }
        }
    }
    </script>

我的登录 controller 是:

       <?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
use Illuminate\Support\Facades\Validator;
use App\Models\User;
class LoginController extends Controller
{
    public function login(Request $request)
    {
        $request->validate([
            'email' => ['required', 'email'],
            'password' => ['required']
        ]);

        if (Auth::attempt($request->only('email', 'password'))){
            return response()->json(Auth::user(), 200);
        }
        throw ValidationException::withMessages([
            'email' =>['The provided credentials are incorect.']
        ]);


        // $request->validate([
        //     'email' => 'required|email',
        //     'password' => 'required',
        //     'device_name' => 'required',
        // ]);

         $user = User::where('email', $request->email)->first();

        // if (! $user || ! Hash::check($request->password, $user->password)) {
        //     throw ValidationException::withMessages([
        //         'email' => ['The provided credentials are incorrect.'],
        //     ]);
        // }

        // return $user->createToken($request->device_name)->plainTextToken;
        return response()->json(['msg' => 'register done']);

    }
}
  • 有人帮我保护路线吗? 我已经工作了两天来解决这个问题

如果你打算使用 sanctum 来验证你的应用程序,你需要

  • 将中间件添加到您的 kernel
  • 使用凭证发出 axios 请求
  • 请求获取 csrf:
    axios.get('/sanctum/csrf-cookie').then(response => {
        // Login...
    });

在您的情况下,我认为您缺少 csrf,并确保您在同一个域下。

在你的情况下:

   loginUser(){
          axios.get('/sanctum/csrf-cookie').then(response => {
    
             axios.post('/api/login', this.form).then(() =>{
                    this.$router.push({ name: 'MainPage' })
                 }).catch((error) =>{
                      this.errors = error.response.data.errors;
                })
         })
   }

在这里查看我的 repo 以获得工作参考laravel-vue-sanctum-spa 样板

查看官方文档sanctum docs

就我个人而言,我会在文章中添加一个属性,例如 public。

由于公共用户未登录,因此为公共用户创建单独的路由。 由于您现在使用的方法需要经过身份验证的用户。

public function unauthorizedIndex()
{
   return Article::where('public', true)->get()
}

我个人认为您仍然需要访问令牌(不记名令牌)并使用 postman 之类的应用程序首先测试 API。

class LoginController extends Controller
{
    use ApiResponser;

    public function __invoke(Request $request)
    {
        // attempting login
        if(!auth()->attempt($request->only('email', 'password'))) {
            return $this->error(401, 'Credentials not match' );
        }

        // Delete old tokens
        auth()->user()->tokens()->delete();

        // Succesfull login and new token created.
        return $this->success([
            'token' => auth()->user()->createToken('API Token', auth()->user()->abilities())->plainTextToken
        ]);
    }

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM