当前位置: 首页 > 知识库问答 >
问题:

如何实施认证

方梓
2023-03-14

我正在尝试实现身份验证

  1. 可以请求任何微服务的API网关。
  2. 用户微服务-我存储所有用户的地方。laravel/护照实现在此微服务中对用户进行身份验证。按应有的方式工作,登录路由返回我用于在此微服务中对用户进行身份验证的令牌。
  3. 其他5个微服务,未经任何身份验证或授权。

问题是:使用身份验证的正确方法是什么

共有1个答案

丌官子安
2023-03-14

我将尝试用< code>API的一个基本示例来解释。

假设您当前有3个微服务

  1. 用户
  2. 职位
  3. 核心

我假设您使用httpOnlycookie来存储用户令牌。

在核心微服务中,我有以下路由结构:

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']);

    });
});

现在我想登录,我应该发送一个< code>API请求,我应该想出一个解决方案,在我需要的任何时候发送< code >令牌。

  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);
    }
}

如果你想知道这个<code>UserService</code>来自哪里,那么我应该说,我已经创建了一个包,可以在其他微服务中使用它,所以你可以这样做,或者只创建一个服务,然后在你的微服务等中使用它。

ApiService的一切都是显而易见的,但我将尝试解释其基础。

    < li >每当我们想要进行< code>API调用时,我们可以简单地调用该类中的< code>Allowed methods,然后我们的方法将调用request,以传递公共参数,并最终使用这些参数来进行< code>API调用。 < li> getRequest方法正在执行调用,并从< code>httpOnly cookie中获取存储的令牌,并将它作为< code>Authorization标头发送到目标endpoint,最终它将返回从目标获取的任何内容。

所以如果我们想使用它,我们可以简单地在我们的控制器中这样做:

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();
    }
}

这是一个完整的示例,您可以在其他微服务上使用核心< code >微服务方法来获取与已验证用户相关的信息,正如您所看到的,由于从< code >核心到其他微服务的< code >请求,所有内容都将得到验证。

 类似资料:
  • 在Perl中,使用Moo,可以围绕sub实现sub,它将围绕类中的其他方法。 如何在Raku中实现这种行为,最好使用角色?

  • 问题内容: 在简要回顾了Go语言规范,有效的Go和Go内存模型之后,我仍然不清楚Go通道是如何工作的。 它们是什么样的结构?它们的行为有点像线程安全队列/数组。 它们的实现取决于体系结构吗? 问题答案: 通道的源文件位于/src/pkg/runtime/chan.go中(从您的源代码根目录开始)。 是通道的中央数据结构,带有发送和接收链接列表(持有指向其goroutine和data元素的指针)和一

  • 问题内容: 几乎每个人都使用它们,但是包括我在内的许多人只是简单地认为它们只是在起作用。 我正在寻找高质量的材料。我使用的语言是:Java,C,C#,Python,C ++,所以这些是我最感兴趣的。 现在,C ++可能是一个不错的起点,因为您可以使用该语言编写任何东西。 而且,C接近组装。如何使用纯C构造而不使用汇编来模拟异常? 最后,我听说有传言称,出于速度考虑,Google员工在某些项目中不使

  • 在新gem的初始起草中,我需要保留一些方法实现为空(将在下一步中实现) 因此,我想发出“尚未实现”异常的信号 我想知道是否有特定于Ruby语言的最佳实践或标准约定来编码这种占位符/异常。 例如:类似于: Java中的操作异常 在. net框架(C#)中没有实现异常

  • 问题内容: Try-catch旨在帮助处理异常。这意味着它将以某种方式帮助我们的系统更强大:尝试从意外事件中恢复。 我们怀疑在执行和指令(发送消息)时可能会发生某些事情,因此将其包含在try中。如果发生了几乎不可预料的事情,我们可以采取一些措施:编写渔获物。我不认为我们打电话来只是记录异常。我认为catch块旨在为我们提供从错误中恢复的机会。 现在,假设我们从错误中恢复了,因为我们可以修复错误所在

  • 本文向大家介绍如何实施区块链项目?相关面试题,主要包含被问及如何实施区块链项目?时的应答技巧和注意事项,需要的朋友参考一下 回答:**请按照以下步骤实施区块链项目。 选择你的平台 初始化区块链 选择正确的共识协议 执行您的第一个智能合约 调试和扩展