I haven’t written PHP code for a long time, especially Lumen. I’m a big Lumen user, and I’ve been using Lumen as the main framework for my API ever since it came out.

But when it comes to API, we have to say a concept: “front and back end separation”. Now more and more teams are using the front and back end separation, completely liberating the advantages of the front end and making the back end more focused on the output of data. Discussion on this aspect is not discussed here, you can refer to some articles for in-depth research:

Segmentfault.com/a/119000000…

Because of the separation of the front and back ends, the background focuses on the output of the interface API, and Lumen was born for RESTful apis at that time:

Decidedly Laravel. Delightfully Minimal.

Lightning fast micro-services and APIs delivered with the elegance you expect.

Using Lumen as an interface framework requires solving a core problem: how to “authenticate” your visitors.

User authentication

Lumen and Laravel use the same underlying class library implementation, but because Lumen is oriented to stateless API development, does not support session, so the default configuration is different. Lumen must be implemented using stateless mechanisms such as API tokens.

Let’s take a look at the Lumen website for an example:

use Illuminate\Http\Request;

$app->get('/post/{id}'['middleware'= >'auth'.function (Request $request, $id) {
    $user = Auth::user();

    $user = $request->user();

    //
}]);Copy the code

It uses middleware: ‘middleware’ => ‘auth’. Let’s look at the auth middleware function:

$app->routeMiddleware([
     'auth' => App\Http\Middleware\Authenticate::class,
 ]);Copy the code

The corresponding class is Authenticate. We look at the Handle function of Authenticate:

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        if ($this->auth->guard($guard)->guest()) {
            return response('Unauthorized.'.401);
        }

        return $next($request);
    }Copy the code

$this->auth->guard($guard)->guest(); Let’s follow the code into AuthManager:

/**
     * Attempt to get the guard from the local cache.
     *
     * @param  string  $name
     * @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard
     */
    public function guard($name = null)
    {
        $name = $name? :$this->getDefaultDriver();

        return isset($this->guards[$name])?$this->guards[$name]
                    : $this->guards[$name] = $this->resolve($name);
    }Copy the code

$this->getDefaultDriver();

/**
     * Get the default authentication driver name.
     *
     * @return string
     */
    public function getDefaultDriver(a)
    {
        return $this->app['config'] ['auth.defaults.guard'];
    }Copy the code

This is now in the default config:

Lumen source code can be seen Lumen’s default authentication “API”.

Let’s take a look at Laravel’s default authentication:

Laravel uses the Web mode by default, and the Web mode uses sessions for user authentication. And that’s a good example of Lumen’s statelessness.

Then we need to understand how Lumen uses the “API” to authenticate users.

The AuthServiceProvider is stored in the app/Providers folder, which contains only one Auth::viaRequest call. ViaRequest is called when the system needs authentication. This method takes an anonymous function argument. In this anonymous function, you can parse App\User arbitrarily and return, or return null if the parse fails, as in:

/**
     * Boot the authentication services for the application.
     *
     * @return void
     */
    public function boot(a)
    {
        // Here you may define how you wish users to be authenticated for your Lumen
        // application. The callback which receives the incoming request instance
        // should return either a User instance or null. You're free to obtain
        // the User instance via an API token or any other method necessary.

        $this->app['auth']->viaRequest('api'.function ($request) {
            if ($request->input('api_token')) {
                return User::where('api_token', $request->input('api_token'))->first(); }}); }Copy the code

Let’s look at the viaRequest function:

/**
     * Register a new callback based request guard.
     *
     * @param  string  $driver
     * @param  callable  $callback
     * @return $this
     */
    public function viaRequest($driver, callable $callback)
    {
        return $this->extend($driver, function (a) use ($callback) {
            $guard = new RequestGuard($callback, $this->app['request'].$this->createUserProvider());

            $this->app->refresh('request', $guard, 'setRequest');

            return $guard;
        });
    }Copy the code

The key here is RequestGuard, the core function of this class:

/**
     * Get the currently authenticated user.
     *
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function user(a)
    {
        // If we've already retrieved the user for the current request we can just
        // return it back immediately. We do not want to fetch the user data on
        // every call to this method because that would be tremendously slow.
        if (! is_null($this->user)) {
            return $this->user;
        }

        return $this->user = call_user_func(
            $this->callback, $this->request, $this->getProvider()
        );
    }Copy the code

This is to determine whether to retrieve user information, mainly by calling the callback function, which we passed in from viaRequest:

function ($request) {
    if ($request->input('api_token')) {
                return User::where('api_token', $request->input('api_token'))->first(); }}Copy the code

This is just an example of validating a User, determining whether the request passed the API_token parameter, and retrieving User or NULL through the User Model direct match lookup.

Of course, in actual development, we cannot simply obtain api_token and directly associate it with the database to find user information.

In API development, user authentication is the core and the premise of data security. At present, there are two commonly used methods for user authentication: JWT and OAuth2.

The next step

At present, we only have a simple understanding of Lumen’s “user authentication”. Next, through the study of “JWT”, we will see how to use JWT to effectively authenticate users and ensure that interface information is accessed by effective users more safely.

Json Web Token (JWT) is an open jSON-based standard (RFC 7519) implemented for the transfer of declarations between network application environments. The token is designed to be compact and secure, especially suitable for single sign-on (SSO) scenarios in distributed sites. The JWT declaration is generally used to pass authenticated user identity information between the identity provider and the service provider to obtain resources from the resource server, and to add some additional declaration information necessary for other business logic. The token can also be used directly for authentication or can be encrypted.

“To be continued”


Coding01 looks forward to your continued attention

qrcode