如何实施身份验证&微服务与amp; amp;授权使用Laravel的API网关

发布于 2025-02-06 20:41:17 字数 422 浏览 2 评论 0原文

我正在尝试实施身份验证&在我的微服务和API网关之间授权用户。我现在拥有的:

  1. 可以向任何微服务请求的API网关。
  2. 用户微服务 - 我存储所有用户的位置。 Laravel/Passport实现了以在此微服务中对用户进行身份验证。登录路线返回的工作原理,我使用的是 微服务的用户来验证用户。
  3. 其他5个微服务,没有任何身份验证或授权。

问题是:使用身份验证的正确方法是什么用微服务授权?我知道我应该在 API网关中对用户进行身份验证,并且授权将在微服务中进行。但是,如果其他微服务对用户一无所知,他们会发生授权吗? 我打算以某种方式使用 jwt 代币以及有关用户角色的信息,但尚未找到如何将这些信息放入令牌

I'm trying to implement authentication & authorization of users between my microservices and API Gateway.What I have now:

  1. API Gateway which can request to any microservice.
  2. User microservice - where I'm storing all users. laravel/passport implemented to authenticate user in this microservice. Works as it should be, login route returns token which I'm using to authenticate user in this microservice.
  3. Other 5 microservices without any authentication or authorization.

Question is: what is the right way to use authentication & authorization with microservices? I know that I should authenticate users in my API Gateway and authorization will happen inside microservices. But how authorization in other microservices happening if they don't know anything about users?
I'm planning to use somehow JWT token with information about user roles but haven't found yet how to put that information into token

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

哭了丶谁疼 2025-02-13 20:41:17

我将尝试用api的基本示例来解释。

假设您当前有3个microservices

  1. 用户
  2. 发布
  3. 核心,

我假设您正在使用httponly cookie来存储用户令牌。

在核心microservice中,我有此路由结构:

Route::prefix('core')->group(function () {
    Route::post('register', [AuthController::class, 'register']);
    Route::post('login', [AuthController::class, 'login']);

    Route::middleware('scope.trader')->group(function () {
        Route::get('user', [AuthController::class, 'user']);

    });
});

现在我想登录,我应该发送api请求,我应该考虑一个解决方案来发送token token < /代码>我需要它。

  1. 登录(这是您获得令牌的地方),并且注册不需要令牌
  2. 用户需要令牌(这是您要求解决方案的地方),

因此除了获得结果外,我还应该为用户创建服务,在这里如何完成了:

UserService :
class UserService extends ApiService
{
    public function __construct()
    {
        // Get User Endpoint Microservice API URL
        $this->endpoint = env('USERS_MS') . '/api';
    }
}
ApiService :
abstract class ApiService
{
    protected string $endpoint;

    public function request($method, $path, $data = [])
    {
        $response = $this->getRequest($method, $path, $data);

        if ($response->ok()) {return $response->json();};

        throw new HttpException($response->status(), $response->body());
    }

    public function getRequest($method, $path, $data = [])
    {
        return \Http::acceptJson()->withHeaders([
            'Authorization' =>  'Bearer ' . request()->cookie('token')
        ])->$method("{$this->endpoint}/{$path}", $data);
    }

    public function post($path, $data)
    {
        return $this->request('post', $path, $data);
    }

    public function get($path)
    {
        return $this->request('get', $path);
    }

    public function put($path, $data)
    {
        return $this->request('put', $path, $data);
    }

    public function delete($path)
    {
        return $this->request('delete', $path);
    }
}

如果您想知道,此uservice来自哪里在您的微服务等中使用并使用它。

关于apiservice,一切都很明显,但我会尝试解释基础。

  1. 每当我们想执行api调用时,我们都可以在此类中调用允许的方法,然后我们的方法将调用请求,以传递常见参数,并最终使用这些进行api调用的参数。
  2. getRequest方法,正在执行呼叫,并从httponly cookie获取存储的令牌,并将其作为授权>授权标题发送到目标端点,最终,它将返回目标。

因此,如果我们想使用此操作,我们可以简单地在控制器中这样做:

class AuthController extends Controller
{
    // use Services\UserService;
    public UserService $userService;

    /**
     * @param UserService $userService
     */
    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }

    public function register(RegisterRequest $request)
    {
        $data = $request->only('name', 'email', 'password') + ['additional_fileds' => 0 ];
        // additional fields can be used for something except from request and
        // optional, like is it admin or user or etc.

        // call the post method, pass the endpoint url(`register`), pass $data
        $user = $this->userService->post('register', $data);
        // get data from target endpoint
        // and ...
        return response($user, Response::HTTP_CREATED);
    }

    public function login(Request $request)
    {
        // same thing here again, but this time i passed scope to help me
        // get the specific user scope
        $data = $request->only('email', 'password') + ['scope' => 'writer'];

        $response = $this->userService->post('login', $data);
        // as you can see when user do success login, we will get token,
        // which i got that token using Passport and set it to $cookie
        $cookie = cookie('token', $response['token'], 60 * 24); // 1 day
      
        // then will set a new httpOnly token on response.
        return response([
            'message' => 'success'
        ])->withCookie($cookie);
    }

    public function user(Request $request)
    {
        // Here, base on userService as you saw, we passed token in all requests
        // which if token exist, we get the result, since we're expecting
        // token to send back the user informations.

        $user = $this->userService->get('user');

        // get posts belong to authenticated user
        $posts = Post::where('user_id', $user['id'])->get();

        $user['posts'] = $posts;

        return $user;
    }
}

现在,用户微服务呢?好吧,这里的一切都很清楚,它应该像基本的应用程序一样工作。

这是路线:

Route::post('register', [AuthController::class, 'register']);
Route::post('login', [AuthController::class, 'login']);

Route::middleware(['bunch','of', 'middlewares'])->group( function (){
    Route::get('user', [AuthController::class, 'user']);
});

在控制器中:

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $user = User::create(
            $request->only('first_name', 'email', 'additional_field')
            + ['password' => \Hash::make($request->input('password'))]
        );

        return response($user, Response::HTTP_CREATED);
    }


    public function login(Request $request)
    {
        if (!\Auth::attempt($request->only('email', 'password'))) {
            return response([
                'error' => 'user or pass is wrong or whatever.'
            ], Response::HTTP_UNAUTHORIZED);
        }

        $user = \Auth::user();

        $jwt = $user->createToken('token', [$request->input('here you can pass the required scope like trader as i expalined in top')])->plainTextToken;

        return compact('token');
    }

    public function user(Request $request)
    {
        return $request->user();
    }
}

因此,这是一个完整的示例,您可以在其他微服务上使用Core microService方法,以获取与已验证的用户有关的信息,并且您可以看到所有内容都将得到认证从core> core到其他微服务。

I'll try to explain with a basic example for API.

Let's say you have currently 3 microservices :

  1. Users
  2. Posts
  3. Core

I assume you're using httpOnly cookie to store user token.

In Core microservice I have this route structure:

Route::prefix('core')->group(function () {
    Route::post('register', [AuthController::class, 'register']);
    Route::post('login', [AuthController::class, 'login']);

    Route::middleware('scope.trader')->group(function () {
        Route::get('user', [AuthController::class, 'user']);

    });
});

Now i want to login which i should send an API request, and I should think of a solution to send token anytime I need it.

  1. login(this is where you get token) and register don't need token
  2. user need token (this is where you asked for solution)

So in addition to get a result, I should create a service for user, and here how I've done it :

UserService :
class UserService extends ApiService
{
    public function __construct()
    {
        // Get User Endpoint Microservice API URL
        $this->endpoint = env('USERS_MS') . '/api';
    }
}
ApiService :
abstract class ApiService
{
    protected string $endpoint;

    public function request($method, $path, $data = [])
    {
        $response = $this->getRequest($method, $path, $data);

        if ($response->ok()) {return $response->json();};

        throw new HttpException($response->status(), $response->body());
    }

    public function getRequest($method, $path, $data = [])
    {
        return \Http::acceptJson()->withHeaders([
            'Authorization' =>  'Bearer ' . request()->cookie('token')
        ])->$method("{$this->endpoint}/{$path}", $data);
    }

    public function post($path, $data)
    {
        return $this->request('post', $path, $data);
    }

    public function get($path)
    {
        return $this->request('get', $path);
    }

    public function put($path, $data)
    {
        return $this->request('put', $path, $data);
    }

    public function delete($path)
    {
        return $this->request('delete', $path);
    }
}

If you're wondering where, this UserService come from, then I should say, I've created a package to use it in other microservices, so you can do the same or just create a service and use it in your microservices or etc.

Everything is obvious about ApiService, but I'll try to explain the base.

  1. Anytime we want to do an API call, we can simply call Allowed methods in this class, then our methods, will call request, to pass common arguments, and eventually using those arguments to do the API call.
  2. getRequest method, is doing the call and get the stored token from httpOnly cookie, and will send it as an Authorization header to the target endpoint, and eventually it'll return whatever it get from target.

So If we want to use this, we can simply do like this in our controller :

class AuthController extends Controller
{
    // use Services\UserService;
    public UserService $userService;

    /**
     * @param UserService $userService
     */
    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }

    public function register(RegisterRequest $request)
    {
        $data = $request->only('name', 'email', 'password') + ['additional_fileds' => 0 ];
        // additional fields can be used for something except from request and
        // optional, like is it admin or user or etc.

        // call the post method, pass the endpoint url(`register`), pass $data
        $user = $this->userService->post('register', $data);
        // get data from target endpoint
        // and ...
        return response($user, Response::HTTP_CREATED);
    }

    public function login(Request $request)
    {
        // same thing here again, but this time i passed scope to help me
        // get the specific user scope
        $data = $request->only('email', 'password') + ['scope' => 'writer'];

        $response = $this->userService->post('login', $data);
        // as you can see when user do success login, we will get token,
        // which i got that token using Passport and set it to $cookie
        $cookie = cookie('token', $response['token'], 60 * 24); // 1 day
      
        // then will set a new httpOnly token on response.
        return response([
            'message' => 'success'
        ])->withCookie($cookie);
    }

    public function user(Request $request)
    {
        // Here, base on userService as you saw, we passed token in all requests
        // which if token exist, we get the result, since we're expecting
        // token to send back the user informations.

        $user = $this->userService->get('user');

        // get posts belong to authenticated user
        $posts = Post::where('user_id', $user['id'])->get();

        $user['posts'] = $posts;

        return $user;
    }
}

Now, how about user microservice? well Everything is clear here, and it should work like a basic app.

Here's the routes :

Route::post('register', [AuthController::class, 'register']);
Route::post('login', [AuthController::class, 'login']);

Route::middleware(['bunch','of', 'middlewares'])->group( function (){
    Route::get('user', [AuthController::class, 'user']);
});

And in controller :

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $user = User::create(
            $request->only('first_name', 'email', 'additional_field')
            + ['password' => \Hash::make($request->input('password'))]
        );

        return response($user, Response::HTTP_CREATED);
    }


    public function login(Request $request)
    {
        if (!\Auth::attempt($request->only('email', 'password'))) {
            return response([
                'error' => 'user or pass is wrong or whatever.'
            ], Response::HTTP_UNAUTHORIZED);
        }

        $user = \Auth::user();

        $jwt = $user->createToken('token', [$request->input('here you can pass the required scope like trader as i expalined in top')])->plainTextToken;

        return compact('token');
    }

    public function user(Request $request)
    {
        return $request->user();
    }
}

So here's the complete example and you can use the Core microservice approach on other microservices to get your information related to authenticated user, and as you can see everything will be authenticated due to those requests from core to other microservices.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文