Home  >  Article  >  PHP Framework  >  Filling in the pit records: laravel passport combined with mobile phone SMS login

Filling in the pit records: laravel passport combined with mobile phone SMS login

藏色散人
藏色散人forward
2021-12-27 15:17:272221browse

The following tutorial column of Laravel will introduce to you the issues related to the combination of laravel passport and mobile phone SMS login. I hope it will be helpful to everyone!

Preparation steps

laravel passport environment

How to install and use, just read the documentation and record the text messages here. Pitfalls and how to combine them with passport

Pit 1

easy-sms package to connect to Tencent Cloud, please use version 1.3 and version 2.0 will always report errors and cannot be sent out. I have tested it repeatedly. It has fooled me several times. If the code contains letters, it will prompt me that there is a problem with my signature. Real-name diss. The interface of Tencent Cloud is simply speechless.

trap二

Determine if the verification code matches, create a user, then how to give him a token? Baidu has a bunch of methods, there are all kinds of miscellaneous things, I have tried everything, how about only supporting laravel5, a few points, or else what version? How is it?

if ($innerVerificationCode==$verificationCode) {
  //验证码成功成功,判断是由在数据库中有此手机用户,有立即给他token 没有 创建后给他token
  $user=User::query()->where('phone_number', $phoneNumber)->first();
 if (!$user) {
  $user = new User();
  $user->name = $phoneNumber;
  $user->phone_number= $phoneNumber;
  $user->login_type=User::USER_LOGIN_TYPE_PHONE;
  $user->password = bcrypt('12345678');
  $user->save();
  }
  return $this->getToken($user, 'id');
}
// 原本一直在纠结如何不用账号密码直接给他 access_token 但是种种原因不是失败了吗 那就 api 请求下
public function getToken($user, $type)
    {
        $http = new \GuzzleHttp\Client();
        $response = $http->post(config('app.url').'/api/fund/oauth/token', [
            'form_params' => [
                'grant_type' => 'password',
                'username' => $user->$type,//用户可以直接登录的用户名,配置后也可以是邮箱,5.8版本,这个默认是注册后的邮箱
                'password' => '12345678',//用户名对应的密码
                'scope' => '*',
            ],
        ]);
        return  json_decode($response->getBody(), false);
    }

The code of the access_token interface is as follows:

<?php
namespace App\Http\Controllers\Api;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Psr\Http\Message\ServerRequestInterface;
use \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Validator;
class AccessTokenController extends \Laravel\Passport\Http\Controllers\AccessTokenController
{
    /**
     * Show User Token
     *
     * 获取用户登录令牌信息
     *
     * @bodyParam username string required 用户名 Example: admin@localhost.com
     * @bodyParam password string required 密码 Example: 123456
     * @bodyParam is_register boolean  是否为注册操作 Example: true
     * @bodyParam subscribe boolean  订阅状态 Example: true
     * @bodyParam grant_type string 授权类型默认password No-example
     * @bodyParam scope string 授权范围默认* No-example
     * @responseFile responses/AccessToken.List.example2.json
     */
    public function issueToken(ServerRequestInterface $rawRequest)
    {
        //获取传入参数
        $request = collect($rawRequest->getParsedBody());
        $validator = Validator::make($request->all(), [
            &#39;username&#39; => &#39;required&#39;,
            &#39;password&#39; => &#39;required&#39;,
        ])->validate();
        $checkUser = \App\Models\User::where("id", $request->get("username"))->first();
        if (!Hash::check($request->get("password"), $checkUser->password)) {
            throw new UnauthorizedHttpException(&#39;Unauthenticated&#39;, "login failed,username error or password error");
        }
        $oauthClient = DB::table(&#39;oauth_clients&#39;)->where("password_client", 1)->first();
        if (empty($oauthClient)) {
            throw new \ErrorException(&#39;can not get oauth client information&#39;);
        }
        //获取其他参数
        $addRequest = [
            &#39;grant_type&#39; => $request->get("grant_type", "password"),
            &#39;client_id&#39; => $request->get("client_id", $oauthClient->id),
            &#39;client_secret&#39; => $request->get("client_secret", $oauthClient->secret),
            &#39;scope&#39; => $request->get("scope", "*"),
        ];
        //重写传入参数
        $newRawRequest = $rawRequest->withParsedBody(array_merge($request->all(), $addRequest));
        return parent::issueToken($newRawRequest);
    }
    /**
     * revoke token
     *
     * 吊销令牌
     *
     */
    public function revokeToken()
    {
        if(Auth::user()){
            $tokenId = Auth::user()->token()->id;
            $tokenRepository = app(&#39;Laravel\Passport\TokenRepository&#39;);
            $tokenRepository->revokeAccessToken($tokenId);
        }
        return response(&#39;&#39;, 204);
    }
}

Record to yourself that the writing of this article is not good, just record that I am busy now

I found it Another better

<?php
namespace App\Traits;
//这里请引用自己的User Model
use App\Models\Users\User;
use DateTime;
use GuzzleHttp\Psr7\Response;
use Illuminate\Events\Dispatcher;
use Laravel\Passport\Bridge\AccessToken;
use Laravel\Passport\Bridge\AccessTokenRepository;
use Laravel\Passport\Bridge\Client;
use Laravel\Passport\Bridge\RefreshTokenRepository;
use Laravel\Passport\Bridge\Scope;
use Laravel\Passport\Passport;
use Laravel\Passport\TokenRepository;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException;
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
/**
 * Trait PassportToken
 *
 * @package App\Traits
 */
trait PassportToken
{
    /**
     * Generate a new unique identifier.
     *
     * @param int $length
     *
     * @throws OAuthServerException
     *
     * @return string
     */
    private function generateUniqueIdentifier($length = 40)
    {
        try {
            return bin2hex(random_bytes($length));
            // @codeCoverageIgnoreStart
        } catch (\TypeError $e) {
            throw OAuthServerException::serverError(&#39;An unexpected error has occurred&#39;);
        } catch (\Error $e) {
            throw OAuthServerException::serverError(&#39;An unexpected error has occurred&#39;);
        } catch (\Exception $e) {
            // If you get this message, the CSPRNG failed hard.
            throw OAuthServerException::serverError(&#39;Could not generate a random string&#39;);
        }
        // @codeCoverageIgnoreEnd
    }
    private function issueRefreshToken(AccessTokenEntityInterface $accessToken)
    {
        $maxGenerationAttempts = 10;
        $refreshTokenRepository = app(RefreshTokenRepository::class);
        $refreshToken = $refreshTokenRepository->getNewRefreshToken();
        $refreshToken->setExpiryDateTime((new \DateTimeImmutable())->add(Passport::refreshTokensExpireIn()));
        $refreshToken->setAccessToken($accessToken);
        while ($maxGenerationAttempts-- > 0) {
            $refreshToken->setIdentifier($this->generateUniqueIdentifier());
            try {
                $refreshTokenRepository->persistNewRefreshToken($refreshToken);
                return $refreshToken;
            } catch (UniqueTokenIdentifierConstraintViolationException $e) {
                if ($maxGenerationAttempts === 0) {
                    throw $e;
                }
            }
        }
    }
    protected function createPassportTokenByUser(User $user, $clientId)
    {
        $accessTokenRepository = new AccessTokenRepository(new TokenRepository(), new Dispatcher());
        $accessToken = $accessTokenRepository->getNewToken(new Client($clientId, null, null), [new Scope("*")], $user->id);
        $accessToken->setIdentifier($this->generateUniqueIdentifier());
        $accessToken->setClient(new Client($clientId, null, null));
        $accessToken->setExpiryDateTime((new \DateTimeImmutable())->add(Passport::tokensExpireIn()));
        $accessTokenRepository->persistNewAccessToken($accessToken);
        $refreshToken = $this->issueRefreshToken($accessToken);
        return [
            &#39;access_token&#39; => $accessToken,
            &#39;refresh_token&#39; => $refreshToken,
        ];
    }
    protected function sendBearerTokenResponse($accessToken, $refreshToken)
    {
        $response = new BearerTokenResponse();
        $response->setAccessToken($accessToken);
        $response->setRefreshToken($refreshToken);
        $privateKey = new CryptKey(&#39;file://&#39;.Passport::keyPath(&#39;oauth-private.key&#39;),null,false);
        $accessToken->setPrivateKey($privateKey);
        $response->setPrivateKey($privateKey);
        $response->setEncryptionKey(app(&#39;encrypter&#39;)->getKey());
        return $response->generateHttpResponse(new Response);
    }
    /**
     * @param User $user
     * @param $clientId
     * @param bool $output
     * @return mixed|\Psr\Http\Message\ResponseInterface
     */
    protected function getBearerTokenByUser(User $user, $clientId, $output = true)
    {
        $passportToken = $this->createPassportTokenByUser($user, $clientId);
        $bearerToken = $this->sendBearerTokenResponse($passportToken[&#39;access_token&#39;], $passportToken[&#39;refresh_token&#39;]);
        if (! $output) {
            $bearerToken = json_decode($bearerToken->getBody()->__toString(), true);
        }
        return $bearerToken;
    }
}
  $user=User::find(2);
        $token =  $this->getBearerTokenByUser($user,6,false);
        return $token;

Related recommendations: The latest five Laravel video tutorials

The above is the detailed content of Filling in the pit records: laravel passport combined with mobile phone SMS login. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:learnku.com. If there is any infringement, please contact admin@php.cn delete