laravel passport 与手机短信登录结合的问题记录

准备步骤

laravel passport环境
怎么安装 怎么使用 看文档就行 这边就记录下和手机短信的坑 和 如何与passport结合

坑一

easy-sms包 对接腾讯云 请用1.3版本 2.0版本 会一致报错发不出去 我反复测试了好几次 简直是坑死我了 并且code如果含有字母 他会提示我的签名有问题 实名diss下腾讯云的接口 简直是 无语死了

坑二

判断验证码匹配上,创建一个用户,那么怎么给他token呢,百度了一堆方法,什么杂七杂八的都有,什么都试过了 要不只支持laravel5点几 要不版本怎么样 要不然怎么样的 简直了

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

access_token接口的代码如下:

<?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(), [
            'username' => 'required',
            'password' => 'required',
        ])->validate();
        $checkUser = \App\Models\User::where("id", $request->get("username"))->first();

        if (!Hash::check($request->get("password"), $checkUser->password)) {
            throw new UnauthorizedHttpException('Unauthenticated', "login failed,username error or password error");
        }

        $oauthClient = DB::table('oauth_clients')->where("password_client", 1)->first();
        if (empty($oauthClient)) {
            throw new \ErrorException('can not get oauth client information');
        }
        //获取其他参数
        $addRequest = [
            'grant_type' => $request->get("grant_type", "password"),
            'client_id' => $request->get("client_id", $oauthClient->id),
            'client_secret' => $request->get("client_secret", $oauthClient->secret),
            'scope' => $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('Laravel\Passport\TokenRepository');
            $tokenRepository->revokeAccessToken($tokenId);
        }
        return response('', 204);
    }
}

给自己记录下 这个文章的文笔不好,随便记录下 现在时间忙

找到了另一种 更好的

<?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('An unexpected error has occurred');
        } catch (\Error $e) {
            throw OAuthServerException::serverError('An unexpected error has occurred');
        } catch (\Exception $e) {
            // If you get this message, the CSPRNG failed hard.
            throw OAuthServerException::serverError('Could not generate a random string');
        }
        // @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 [
            'access_token' => $accessToken,
            'refresh_token' => $refreshToken,
        ];
    }

    protected function sendBearerTokenResponse($accessToken, $refreshToken)
    {
        $response = new BearerTokenResponse();
        $response->setAccessToken($accessToken);
        $response->setRefreshToken($refreshToken);
        $privateKey = new CryptKey('file://'.Passport::keyPath('oauth-private.key'),null,false);

        $accessToken->setPrivateKey($privateKey);
        $response->setPrivateKey($privateKey);
        $response->setEncryptionKey(app('encrypter')->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['access_token'], $passportToken['refresh_token']);
        if (! $output) {
            $bearerToken = json_decode($bearerToken->getBody()->__toString(), true);
        }

        return $bearerToken;
    }
}
  $user=User::find(2);
        $token =  $this->getBearerTokenByUser($user,6,false);
        return $token;
本作品采用《CC 协议》,转载必须注明作者和本文链接
chowjiawei
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 19
GDDD

你应该一直纠结那个获取token的,问题得解决。而且看你获取token里面,密码是明文?后面$checkUser对象都不判断下 就直接用了。

2年前 评论
redis_object 2年前
chowjiawei (楼主) 2年前
GDDD (作者) 2年前
chowjiawei (楼主) 2年前
GDDD (作者) 2年前
chowjiawei (楼主) 2年前
       $this->guard()->login($userInfo);
        //验证成功返回信息
        $user = $this->guard()->user();
        $tokenData = $user->createToken();
        $token = $tokenData->accessToken;

看文档或看一下laravel源码,就知道login方法了。
本质上不限制何种方式登陆,前面验证你自己的获取到用户用户信息,然后执行login方法。在去创建token就行了,这个章节好像是在auth认证里面,auth与passport是有关联的。
代码中$this是Auth

2年前 评论
chowjiawei (楼主) 2年前
xini2603 (作者) 2年前
chowjiawei (楼主) 2年前
王大牛 2年前
chowjiawei (楼主) 2年前
王大牛 2年前
chowjiawei (楼主) 2年前
王大牛 2年前
chowjiawei (楼主) 2年前
chowjiawei

@王大牛 auth.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Defaults
    |--------------------------------------------------------------------------
    |
    | This option controls the default authentication "guard" and password
    | reset options for your application. You may change these defaults
    | as required, but they're a perfect start for most applications.
    |
    */

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    |
    | Next, you may define every authentication guard for your application.
    | Of course, a great default configuration has been defined for you
    | here which uses session storage and the Eloquent user provider.
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | Supported: "session"
    |
    */

    'guards' => [
        'web' => [
            'driver' => 'passport',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'passport',
            'provider' => 'users',
            'hash' => false,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | If you have multiple user tables or models you may configure multiple
    | sources which represent each model / table. These sources may then
    | be assigned to any extra authentication guards you have defined.
    |
    | Supported: "database", "eloquent"
    |
    */

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\Users\User::class,
        ],
        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    |
    | You may specify multiple password reset configurations if you have more
    | than one user table or model in the application and you want to have
    | separate password reset settings based on the specific user types.
    |
    | The expire time is the number of minutes that the reset token should be
    | considered valid. This security feature keeps tokens short-lived so
    | they have less time to be guessed. You may change this as needed.
    |
    */

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
            'throttle' => 60,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Password Confirmation Timeout
    |--------------------------------------------------------------------------
    |
    | Here you may define the amount of seconds before a password confirmation
    | times out and the user is prompted to re-enter their password via the
    | confirmation screen. By default, the timeout lasts for three hours.
    |
    */

    'password_timeout' => 10800,

];
2年前 评论

简单的事情,不要搞复杂了,看这个 github.com/larvatecn/laravel-passp...

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!