Laravel 使用 REST API 源,用于移动设备和浏览器,带有授权。

huangapple go评论127阅读模式
英文:

Laravel using rest api source for both mobile and browser with authorization

问题

根据您提供的信息,您希望将以下文本翻译成中文:

我有一个REST API,根据用户是否经过授权,发布不同的产品 `/api/products`。这个API用于移动应用程序,我通过 `Sanctum` 使用 Bearer Token 进行授权。为了处理来自任何用户的请求,并根据是否存在令牌来显示商品。

我的自定义API中间件

public function handle(Request $request, Closure $next): Response
{
    if ( $request->bearerToken() && Auth::guard('sanctum')->user() )
        Auth::setUser( Auth::guard('sanctum')->user() );

    return $next($request);
}

接下来,我不仅使用API,还使用了一个用于移动应用程序的网站。我决定使用常规的PHP方法,结合Vue组件,使用 `Breeze & Blade` 以及 Vue。据我了解,如果用户通过网站授权,他会收到授权的Cookie,并且它们必须应用于Ajax请求。

我的Vue组件中的axios请求到 `/api/products`。
如果用户通过网站获得授权,那么将应用Cookie并发送

const instance = axios.create({
    timeout: 2000,
   
    // 包括我的Cookie
    withCredentials: true,

    headers: {
      'Access-Control-Allow-Origin': '*',
      'Content-Type': 'application/json',
      'Access-Control-Allow-Credentials': true
    },

    // 带有令牌的请求有效。中间件了解用户是否已经授权
    // headers: {'Authorization': 'Bearer '+'1|XedL48l1TU5KomRxix6xFrsm0v7jw5eTbHzfpoGC';}
  });

  instance
      .post("/api/products",
          {
            data: example_data,
          })
      .then(response => {
        console.log(response.data)
      });

问题在于中间件无法理解随axios请求发送的Cookie。中间件无法判断我是否通过请求附带的Cookie进行了授权。它只了解标头中的令牌,它可以使用令牌。文档中提到 `Sanctum` 中间件可以理解请求中附带的Cookie,但我没有使用 `Sanctum` 中间件。是否有可能以某种方式实现,以便我的自定义中间件能够理解经过授权的用户的Cookie,而不仅仅是令牌?

请注意,您提供的文本中包含一些代码片段,我已经将它们保留在翻译中。以下是翻译好的文本:

根据您提供的信息,您希望将以下文本翻译成中文:

我有一个REST API,根据用户是否经过授权,发布不同的产品 `/api/products`。这个API用于移动应用程序,我通过 `Sanctum` 使用 Bearer Token 进行授权。为了处理来自任何用户的请求,并根据是否存在令牌来显示商品。

我的自定义API中间件

public function handle(Request $request, Closure $next): Response
{
    if ( $request->bearerToken() && Auth::guard('sanctum')->user() )
        Auth::setUser( Auth::guard('sanctum')->user() );

    return $next($request);
}

接下来,我不仅使用API,还使用了一个用于移动应用程序的网站。我决定使用常规的PHP方法,结合Vue组件,使用 `Breeze & Blade` 以及 Vue。据我了解,如果用户通过网站授权,他会收到授权的Cookie,并且它们必须应用于Ajax请求。

我的Vue组件中的axios请求到 `/api/products`。
如果用户通过网站获得授权,那么将应用Cookie并发送

const instance = axios.create({
    timeout: 2000,
   
    // 包括我的Cookie
    withCredentials: true,

    headers: {
      'Access-Control-Allow-Origin': '*',
      'Content-Type': 'application/json',
      'Access-Control-Allow-Credentials': true
    },

    // 带有令牌的请求有效。中间件了解用户是否已经授权
    // headers: {'Authorization': 'Bearer '+'1|XedL48l1TU5KomRxix6xFrsm0v7jw5eTbHzfpoGC';}
  });

  instance
      .post("/api/products",
          {
            data: example_data,
          })
      .then(response => {
        console.log(response.data)
      });

问题在于中间件无法理解随axios请求发送的Cookie。中间件无法判断我是否通过请求附带的Cookie进行了授权。它只了解标头中的令牌,它可以使用令牌。文档中提到 `Sanctum` 中间件可以理解请求中附带的Cookie,但我没有使用 `Sanctum` 中间件。是否有可能以某种方式实现,以便我的自定义中间件能够理解经过授权的用户的Cookie,而不仅仅是令牌?
英文:

I have an rest api that, depending on whether the user is authorized or not, issues different products /api/products. This api for a mobile application, I carry out authorization through a bearer token with Sanctum. To process requests from any users and, depending on whether there is a token or not, display goods.

My custom middleware for api

public function handle(Request $request, Closure $next): Response
    {
        if ( $request->bearerToken() && Auth::guard('sanctum')->user() )
            Auth::setUser( Auth::guard('sanctum')->user() );

        return $next($request);
    }

Next, it took not only api but also a website that will use this api, which is intended for a mobile application. Decided to use the usual php approach using vue components. Its Breeze & Blade with Fortify and Vue. As far as I understand, if the user is authorized through the website, cookies with authorization come to him and they must be applied to Ajax requests.

My axios request from vue component to /api/products.
If the user is authorized through the website, then a cookie is applied and sent

const instance = axios.create({
    timeout: 2000,
   
    //My cookie included
    withCredentials: true,

    headers: {
      'Access-Control-Allow-Origin': '*',
      'Content-Type': 'application/json',
      'Access-Control-Allow-Credentials' : true
       },

    //With token works. Middleware understands that the user is authorized
    //headers: {'Authorization': 'Bearer '+'1|XedL48l1TU5KomRxix6xFrsm0v7jw5eTbHzfpoGC'}
  });

  instance
      .post("/api/products",
          {
            data: example_data,

          }, )
      .then(response => {
        console.log(response.data)
      });

The problem is that the middleware does not understand the cookies that come with the axios request. Middleware can't figure out if I'm authorized or not through the cookies attached to requests. It understands only the token in header, it works with the token.The documentation says that the Sanctum middleware understands the cookies that are attached to the request, but I do not use the middleware sanctum. Is it possible to implement it somehow, so that the authorized user's cookies would be understood by my custom middleware and not just the token?

答案1

得分: 1

I'm the one who answers your first questions.

You do not need to pass things like that when doing request from your front-end which is already authenticated through session.

All you have to is make sure to set with axios with credentials under resources/js/bootstrap.js

import axios from 'axios'
window.axios = axios

window.axios.defaults.withCredentials = true
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

Then you could simply call the end-point from vue template and the middleware would be able to idenfity authenticated request or not

Just a side note, if you authenticating via API tokens, make sure to pass Accept: application/json on your header request

EDIT

your app/Http/Kernel.php should have this lines in $middlewareGroups

protected $middlewareGroups = [
'web' => [
.
.
.
],

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

];

英文:

I'm the one who answers your first questions.

You do not need to pass things like that when doing request from your front-end which is already authenticated through session.

All you have to is make sure to set with axios with credentials under
resources/js/bootstrap.js

import axios from 'axios'
window.axios = axios

window.axios.defaults.withCredentials = true
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'

Then you could simply call the end-point from vue template and the middleware would be able to idenfity authenticated request or not

<script setup>
import { onMounted } from 'vue'

async function getProducts() {
    try {
        const { data } = await axios.get(`/api/products`)
        console.log( data )
    } catch (error) {
        console.log( error.response.message ?? error.message )
    }
}

onMounted( () => {
    getProducts()
})

</script>

Just a side note, if you authenticating via API tokens, make sure to pass Accept: application/json on your header request

EDIT

your app/Http/Kernel.php should have this lines in $middlewareGroups

protected $middlewareGroups = [
    'web' => [
        .
        .
        .
    ],

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

huangapple
  • 本文由 发表于 2023年3月4日 07:54:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/75632784.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定