Laravel5.5+passport 放弃 dingo 开发 API 实战,让 API 开发更省心
Laravel5.5更新,通过Laravel5.5开发Api更加顺畅了,在这里就分享一下Laravel开发Api的经验吧
1.封装返回的统一消息
返回的自定义消息,和错误消息,我自己封装了一个Trait,用来做基本的返回,Trait的封装如下
namespace App\Api\Helpers\Api;
use Symfony\Component\HttpFoundation\Response as FoundationResponse;
use Response;
trait ApiResponse
{
/**
* @var int
*/
protected $statusCode = FoundationResponse::HTTP_OK;
/**
* @return mixed
*/
public function getStatusCode()
{
return $this->statusCode;
}
/**
* @param $statusCode
* @return $this
*/
public function setStatusCode($statusCode)
{
$this->statusCode = $statusCode;
return $this;
}
/**
* @param $data
* @param array $header
* @return mixed
*/
public function respond($data, $header = [])
{
return Response::json($data,$this->getStatusCode(),$header);
}
/**
* @param $status
* @param array $data
* @param null $code
* @return mixed
*/
public function status($status, array $data, $code = null){
if ($code){
$this->setStatusCode($code);
}
$status = [
'status' => $status,
'code' => $this->statusCode
];
$data = array_merge($status,$data);
return $this->respond($data);
}
/**
* @param $message
* @param int $code
* @param string $status
* @return mixed
*/
public function failed($message, $code = FoundationResponse::HTTP_BAD_REQUEST, $status = 'error'){
return $this->setStatusCode($code)->message($message,$status);
}
/**
* @param $message
* @param string $status
* @return mixed
*/
public function message($message, $status = "success"){
return $this->status($status,[
'message' => $message
]);
}
/**
* @param string $message
* @return mixed
*/
public function internalError($message = "Internal Error!"){
return $this->failed($message,FoundationResponse::HTTP_INTERNAL_SERVER_ERROR);
}
/**
* @param string $message
* @return mixed
*/
public function created($message = "created")
{
return $this->setStatusCode(FoundationResponse::HTTP_CREATED)
->message($message);
}
/**
* @param $data
* @param string $status
* @return mixed
*/
public function success($data, $status = "success"){
return $this->status($status,compact('data'));
}
/**
* @param string $message
* @return mixed
*/
public function notFound($message = 'Not Found!')
{
return $this->failed($message,Foundationresponse::HTTP_NOT_FOUND);
}
}
然后创建一个ApiController,通过所有的Api控制器继承该控制器,实现简洁的Api返回
<?php
namespace App\Http\Controllers\Api;
use App\Api\Helpers\Api\ApiResponse;
use App\Http\Controllers\Controller;
class ApiController extends Controller
{
use ApiResponse;
// 其他通用的Api帮助函数
}
然后,Api控制器就可以简洁的返回
<?php
namespace App\Http\Controllers\Api;
class IndexController extends ApiController
{
public function index(){
return $this->message('请求成功');
}
}
2.资源类型的返回
资源返回通过5.5的新特性,API资源实现,具体参见
learnku.com/docs/laravel/5.5/eloqu...
使用方面比之前的Transformer方式更好用更优雅
比如返回用户的分页数据,只需要这样
文档已经很详细了,这里不再做概述
<?php
namespace App\Http\Controllers\Api;
use App\Models\User;
use App\Http\Resources\User as UserCollection;
use Illuminate\Support\Facades\Input;
class IndexController extends ApiController
{
public function index(){
return UserCollection::collection(User::paginate(Input::get('limit') ?: 20));
}
}
3. Api授权模块
这里直接抛弃之前的jwt转向passport的认证方式,之前论坛已经有相关认证的帖子了
这里通过重写AuthenticatesUsers
通过password
的的授权模式模式进行实现
<?php
namespace App\Http\Controllers\Api;
use Carbon\Carbon;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\Auth;
use Laravel\Passport\Client;
use Socialite;
use App\Models\User;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Validator;
class AuthenticateController extends ApiController
{
use AuthenticatesUsers;
public function __construct()
{
$this->middleware('auth:api')->only([
'logout'
]);
}
public function username()
{
return 'phone';
}
// 登录
public function login(Request $request)
{
$validator = Validator::make($request->all(), [
'phone' => 'required|exists:user',
'password' => 'required|between:5,32',
]);
if ($validator->fails()) {
$request->request->add([
'errors' => $validator->errors()->toArray(),
'code' => 401,
]);
return $this->sendFailedLoginResponse($request);
}
$credentials = $this->credentials($request);
if ($this->guard('api')->attempt($credentials, $request->has('remember'))) {
return $this->sendLoginResponse($request);
}
return $this->setStatusCode(401)->failed('登录失败');
}
// 退出登录
public function logout(Request $request)
{
if (Auth::guard('api')->check()){
Auth::guard('api')->user()->token()->revoke();
}
return $this->message('退出登录成功');
}
// 第三方登录
public function redirectToProvider($driver) {
if (!in_array($driver,['qq','wechat'])){
throw new NotFoundHttpException;
}
return Socialite::driver($driver)->redirect();
}
// 第三方登录回调
public function handleProviderCallback($driver) {
$user = Socialite::driver($driver)->user();
$openId = $user->id;
// 第三方认证
$db_user = User::where('xxx',$openId)->first();
if (empty($db_user)){
$db_user = User::forceCreate([
'phone' => '',
'xxUnionId' => $openId,
'nickname' => $user->nickname,
'head' => $user->avatar,
]);
}
// 直接创建token
$token = $db_user->createToken($openId)->accessToken;
return $this->success(compact('token'));
}
//调用认证接口获取授权码
protected function authenticateClient(Request $request)
{
$credentials = $this->credentials($request);
// 个人感觉通过.env配置太复杂,直接从数据库查更方便
$password_client = Client::query()->where('password_client',1)->latest()->first();
$request->request->add([
'grant_type' => 'password',
'client_id' => $password_client->id,
'client_secret' => $password_client->secret,
'username' => $credentials['phone'],
'password' => $credentials['password'],
'scope' => ''
]);
$proxy = Request::create(
'oauth/token',
'POST'
);
$response = \Route::dispatch($proxy);
return $response;
}
protected function authenticated(Request $request)
{
return $this->authenticateClient($request);
}
protected function sendLoginResponse(Request $request)
{
$this->clearLoginAttempts($request);
return $this->authenticated($request);
}
protected function sendFailedLoginResponse(Request $request)
{
$msg = $request['errors'];
$code = $request['code'];
return $this->setStatusCode($code)->failed($msg);
}
}
4.自定义返回异常
这里我的做法是直接拦截App\Exceptions\Handler
的render
方法,实现自定义返回
<?php
namespace App\Exceptions;
use App\Api\Helpers\Api\ExceptionReport;
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class Handler extends ExceptionHandler
{
/**
* 其他代码...
*/
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $exception)
{
// 将方法拦截到自己的ExceptionReport
$reporter = ExceptionReport::make($exception);
if ($reporter->shouldReturn()){
return $reporter->report();
}
return parent::render($request, $exception);
}
}
然后在该方法实现自定义返回
<?php
namespace App\Api\Helpers\Api;
use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Request;
class ExceptionReport
{
use ApiResponse;
/**
* @var Exception
*/
public $exception;
/**
* @var Request
*/
public $request;
/**
* @var
*/
protected $report;
/**
* ExceptionReport constructor.
* @param Request $request
* @param Exception $exception
*/
function __construct(Request $request, Exception $exception)
{
$this->request = $request;
$this->exception = $exception;
}
/**
* @var array
*/
public $doReport = [
AuthenticationException::class => ['未授权',401],
ModelNotFoundException::class => ['该模型未找到',404]
];
/**
* @return bool
*/
public function shouldReturn(){
if (! ($this->request->wantsJson() || $this->request->ajax())){
return false;
}
foreach (array_keys($this->doReport) as $report){
if ($this->exception instanceof $report){
$this->report = $report;
return true;
}
}
return false;
}
/**
* @param Exception $e
* @return static
*/
public static function make(Exception $e){
return new static(\request(),$e);
}
/**
* @return mixed
*/
public function report(){
$message = $this->doReport[$this->report];
return $this->failed($message[0],$message[1]);
}
}
好啦,所有的基础模块都构建完了,现在就可以开发你需要的业务逻辑啦~
个人博客地址:www.timenotes.me/articles/code/11
欢迎大佬参观~
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由 Summer
于 7年前 加精
赞。最近也在考虑放弃 Dingo,做了些定制后维护起来太麻烦了。
原生的一套兼容等各方面还是比较好。
@HyanCat 是呀,之前的项目就是用Dingo开发的,后台5.5的Api资源的确让人眼前一亮,新开的项目就直接用5.5重构了
请问一下,passport使用密码模式登录,在登录验证的时候报这个错误是怎么回事啊:
控制器代码是这样的:
auth.php配置是这样的:
模型是这样的:
@justinstar
Auth::guard('api')
拿到的是RequestGuard
对象,没有attempt
方法呀,试试Auth::attempt(xxx)
@王举 这样怎么来指定auth.php里面的api呢,
@justinstar 做法是
use AuthenticatesUsers;
使用这个Trait,然后通过$this->guard('api')->attempt([])
的方式,这个会获取SessionGuard
的实例,调用里面的attempt方法,passport
中的RequestGuard
默认没有实现attempt方法,或者你重写一个Guard
都可以@王举 好了,非常感谢:smile:
想问一下,@王举 api 参数校验这一块,你是如何封装并的呢?laravel提供的校验类好像都是针对form表单提交过来的数据校验。
@Thank 前面已经提过可以拦截请求过程的Exception,(4.自定义返回异常)[https://learnku.com/articles/6035/laravel55-developing-api-combat#4自定义返回异常],其实表单验证也是可以拦截的呀
比如,在Api控制器我们用表单验证
然后在我们的拦截器里面拦截
Illuminate\Validation\ValidationException
异常然后就可以直接拦截到之后就可以自定义返回了
效果:

学习了
@王举 好,我先按你的思路进行测试。谢谢。
ApiResponse 里的failed 方法有问题,调用这个方法如果传递 status code 参数的话,status 这个方法就会用400 覆盖掉 setStatusCode 设置的状态吗!
比如 notFound 方法 返回的 status code 是400
另外个人觉得 status 这个方法有悖于 RESTfull API 的设计规范,进行无意义的包装……我之前也是这么做的,但是用 axios 调用接口时,要 response.data.data,这样比较郁闷!
$user->createToken();这个方法创建的是Personal Token 有效期一年,有没有什么方法创建 普通的 AccessToken
@Jinrenjie
多谢指点,已更新。
我觉得status的包装是有必要的,在js你可能觉得这样麻烦,但是api不仅仅用在web,IOS安卓都是要使用的。特别是移动端要根据状态去判断请求的结果。或者拿JSON转换成相应的对象去展示。这样里面包装的data就很有必要了。而且response.data.data的两个data又不冲突,第二个data是可能有可能没的,要根据请求状态判断
Personal Token的有效期可以设置的,具体可以参考这个 https://github.com/laravel/passport/issues...
感觉这样的话应该能满足你的需求
@王举 移动端我没接触过,难道不能根据 HTTP 状态码判断吗?
还有个问题,就是关于 POST、PUT和 PATCH 者三种操作如果成功的话都是返回 201状态码吗?有人说是 PUT和 PATCH 是200,也有人说是201 但是规范上好像说201 是创建新资源对象才返回的状态码!
感谢分享,从你的这篇文章里学到了不少东西:smile: :smile: :smile:
请教个问题,在passport密码授权模式下使用手机号密码登陆获取
access_token
。当接入APP端第三方登陆。这时候如何生成access_token
呢?因为使用第三方授权登陆的时候是没有手机号password等信息的。access_token好像只能请求/oauth/token获取,没有像jwt那样获取
$user
,然后调用fromUser($user)
就可以生成token
.@fnf1993 这个只能创建 Personal Token,根据手机号码获取用户模型,$user->createToken('name_string');
@fnf1993 第三方授权的话我选用这个
然后这样就可以创建Token了
这种个人令牌默认有效期是一年
你可以进行修改,参考:https://github.com/laravel/passport/issues...
使用文档地址:
https://learnku.com/docs/laravel/5.5/passport#管理个人访问令牌
@Jinrenjie thx
我去试试~
@王举 thx
我去看看,非常感谢
@王举 还有个问题

把第三方登陆的标识信息(openid微信、uid微博等存在下图name的位置),那如何区分不同平台呢?
我现在的想法是加个前缀eg.
2.
@王举
2.微博
这样可以嘛?
@fnf1993 可以的,创建token的名字随意
用了半年的 dingo,控制器,依赖注入都被废了。最后放弃了。
@medz 歇了好久没看,到底 passport 和 dingo/api 有啥区别啊,我还是5.2的时候用过dingo
@kylesean 你理解错 Passport 和 dingo/api 了,Passport 是 Laravel 官方提供的 oAuth 2.0 实现包。dingo/api 是一个标准 REST ful API 开发拓展框架。
@medz 哦哦,3Q,可是 dingo/api 不也封装了 oauth 吗? passport 更有优势么?
@kylesean passport 只是单纯封装 oauth。
我直接这样的,在config/code.php里面写所有的错误码和对应的信息。然后调用
@欧阳逸 也是可以的,这个自己感觉怎么省事怎么来
@王举 大哥,我按照你的方法来,请求登录接口的时候
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController {
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
@王举 login的时候$this->guard('api')->attempt($credentials, $request->has('remember')),我这个拿到的也是RequestGard,我没看到你在AuthenticatesUsers这里面写attempt方法啊,我在这里卡住了,能够指导下吗?多谢了
@王举 试过Auth::attempt(),也不行啊。
@欧阳逸 如果你用的是
tymon/jwt-auth
的包的话,升级到1.0.0-rc.1
还要在User 模型里重写一个方法,具体的我也忘记了,你可以参照源码,因为这些在官方文档里都没有得到更新……@Jinrenjie 我直接用的官方自带的passport,没用第三方包
@欧阳逸 Passport 没有 实现Guard的类,他的$this->guard('api')不是passport 的验证方式……
@王举 移动端android ios什么的用http状态码一点问题都没有,实践过多次,如果不是为了RPC接口没必要,而且更方便。 一直没有包装http code在json里,完全没必要!最多就是有一些业务细节的code代码
@ThinkWorld 其实不用也是完全可以的,这个是参考其他api的返回,比如dingo的错误也会返回如下
说不上用不用的好坏,主要是和前端人员沟通好才是最重要的,ios是可以判断,但是打印的json结果如果不带code的话默认是看不到状态码的,要单独在response中拿code,个人感觉还是带了方便一些。
@王举 那就有备无患吧。
有个bug,当我使用
$this->success(new UserCollection(User::paginate()))
返回分页资源时,返回的json数据中没有 meta 和 links 键包含的分页状态信息@ganlanshu0211 resources资源直接返回
或者自定义
@王举 这样不就不能再json数据里面返回status了,想全部做成一样的格式的
@ganlanshu0211 给你个思路,就是重写路由的Api Response 返回
目前没有发现很简单的方法,思路是重写
Json\Resource
的warp
方法直接贴代码了,你自己研究一下
App\Http\Responses\ResourceCollection
App\Http\Responses\PaginatedResourceResponse
App\Http\Responses\ResourceResponse
然后所有的
Resource
都继承自己的App\Http\Responses\Resource
当然,
meta
是我随便定义的,你可以自由定义example
然后所有的资源既可以带你加的meta了
ios工程师初学laravel,特别感谢!
@王举 3Q
用了资源类型的返回,就不知道封装的这个Trait,怎么使用了.
@Ali 是不是错误的返回类型,可以使用封装的这个
@Ali 错误的消息返回,以及特殊的返回格式,用户提示等
@Thank 问您一下,你实验成功了吗.我一直不成功,不走验证这一步.
@Ali 嗯,可能你代码还有问题吧
@王举 也可能是我不知道 怎么调用封装的这些方法吧.
为什么这个 第三方回调方法里你 return 了东西。。。。你返回给谁了。懵逼
@geekzwb 建议你看看这个,就懂啦
http://www.ruanyifeng.com/blog/2014/05/oau...
@王举 我的理解是,这个是第三方比如qq重定向过来的吧。如果你在这个回调方法return success方法, 浏览器页面显示是你返回的 json?
@geekzwb 授权成功会会掉到这里的,这些你都可以参考第三方授权的接口文档,说的很清楚
@王举 我不明白的是,这个返回是发送到 前端的? 对应前端哪个请求? 可是这个回调并不是前端发起的呀,而是qq
@geekzwb 前端请求你的地址 -> 你跳转到第三方授权的地址 -> 授权成功回调你设置的回调地址 -> 处理登录信息
@geekzwb http://wiki.connect.qq.com/%E7%BD%91%E7%AB... 你可以参考qq的第三方登录文档
@王举 前端请求服务端地址,这里的请求是指的跳转还是ajax请求?
@geekzwb 跳转
我创建了一个login的表单请求,
我创建了一个login的表单请求后,就突然开始提示 unsupported_grant_type,感觉八竿子打不着的俩东西,有点懵逼,能帮我解下惑吗?
@Ali 成功了,但没整理成文档。
我想在lumen使用jwt 按照文档进行总是各种报错
这是其中的一处错误
lumen版本5.5 jwt0.5
(1/1) ErrorException
Non-static method Tymon\JWTAuth\JWTAuth::attempt() should not be called statically
有没有相关的安装文档 非常感谢
眼前一亮
@王举 $status = "success" 返回参数中的"status"起到什么作用?,成功失败不是根据code来的吗?code=200表示成功?
@torome 这个用来表示用户的请求状态是否成功,觉得多余可以直接去掉的,没啥关系
大佬 我想问下 如果是单页面应用 在passport密码授权模式下 获取到token 保存在哪里 ?如果别人获取到这个token 是不是对用户的安全方面有一些问题
@墨韵留香 spa的话,直接将token用js保存到localStorge就好了,在 App.vue created的时候拿到它,判断用户的登录状态,如果用户特意拿的话可能会请求到你的相应的接口,如果考虑token安全问题的话,可以考虑token的失效周期或者用户的地理位置检测方面考虑
@王举 嗯嗯 好的 谢谢 我试试用ip 进行判断下
@ganlanshu0211
@王举
关于分页的我想了个办法解决,在
ApiResponse
中增加一个方法来组合数据mark 顺便赞一下
我很无解释~还是没有弄懂怎么设置个人令牌的时间
已经新建了ServiceProvider.php
之后不知道怎么应用....
按你的代都贴去了,对于我这个新手来说,实在不知如何入手啊,能不能给个完整的测试实例啊,
'providers' => [
'admin_users'=>[
'driver'=>'eloquent',
'model' =>App\Models\AdminUser::class,
],
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'api_users' => [
'driver' => 'eloquent',
'model' => App\Models\ApiUser::class,
],
//if ($this->guard('api')->attempt($credentials,$request->has('remember'))) {
// return $this->sendLoginResponse($request);
//}
这个代码 总是出错
原来只支持默认 User模型!!!!!!
mark
大神 想请教一下 ,在你的第三方登录的两个方法中
redirectToProvider
和handleProviderCallback
这两个方法的路由是写在api.php
中 还是web.php
中呢?@dptms 属于web的
@王举 那如果让 laravel 纯粹写 api 第三方登录有什么好的实践办法吗?
@dptms 文档是最好的实践方法啊
看了你的帖子,心里很纠结究竟要不要用dingo,个人也觉得dingo提供的一些我用到的功能,实现方式并不复杂,用上dingo反而显得累赘,担心后期维护起来会很麻烦.顺便提个问题,如果不使用dingo,如何实现api接口的版本控制呢?
@山海王子 个人建议彻底抛弃dingo,后端项目复杂的时候真的用的难受,抛弃Fractal的Transformer,Api资源无论灵活性还是封装都是完全超过Fractal的,以后用的难受了再迁移,为啥不提前直接用新特性呢,dingo自带了版本控制,直接看dingo的文档就知道啦
重要的事要大一点
请问, 如果根据客户端传过来的参数, 动态查找关联模型的数据, 用 Api 资源要怎么实现 ?
研究了一下, 知道怎么玩了~ :)
@王举
手机号和密码是对的 出现图片的那写 这是什么问题啊 帮帮忙 :disappointed_relieved:
@木拉地力 缺少username 字段
@木拉地力 重写
AuthenticatesUsers
的trait的username 方法为你自己的字段,用passport的话,在user模型实现findForPassport
方法@王举
username字段是我用tel字段为用户名的所有使用用户名的地方我都改为tel了
还是一样
@木拉地力 你的错误是请求非法,缺少了一个必选参数,你按照报错好好找一下,自己debug很容易找到的
@王举
我刚才是把上面的username改为tel了所以报刚才那个错误
这个username的值是传过来的密码 可是我数据库字段里的字段是phone(我把tel该phone了)这样对吗
现在改回来了报下面这个图的错误
@木拉地力 左边的username的key不能改,修改的不应该是你右边的
$credentials['xxx']
么,你传的username是tel的话应该就是$credentials['tel']
,和左边对应起来@王举 现在对应起来了报这样的错误
{
"error": "invalid_credentials",
"message": "The user credentials were incorrect."
}
@木拉地力 https://stackoverflow.com/questions/45171367/laravel-passport-register-the-user-credentials-were-incorrect,遇到问题记得谷歌,都很容易找到的
@木拉地力 上面说过要自己实现 『在
User
模型实现findForPassport
方法』对应你的
User
模型应该是这样的,你试试吧。异常无法处理 ,跳去登录页了
@Kerlin 非常感谢你提供的分页思路,真的非常感谢
@王举 个人觉得 封装的这个ExceptionReport 意思不大呢
在封装用中 $this->exception typeof 异常类型 和 在本身的Handler 中判断是一样的
另外更想知道api resource 用Response::json 返回会丢失 meta,links数据等数据而直接return 就不会的原因,不知你有没有见解
@wiladog https://github.com/wowiwj/RApi/blob/4abcf4...
看看这个
@王举 谢谢
根据这篇文章,自定义了一个HelperFunction
在控制器里:
请问这个能不能是实现,手机号码+短信验证码登录认证,可以的话,大概思路是什么?
@984054610 这个具体的功能要你自己写,大致就是 根据手机号 发送验证码,然后将手机号和发送的验证码保存到缓存,并设置缓存周期以及重试次数,在注册的时候拿注册的手机号和验证码进行比对,成功则创建(注册)用户。
这个是一年前写的注册;逻辑,你可以参考一下
https://github.com/wowiwj/LifeRecoder-Serv...
@王举 我在用这个方法在本地Homestead可以顺利获取到access_token,获取用户也没有问题,部署到服务器上之后,也可以顺利的获取到access_token,然后使用access_token获取用户之后,提示
本地这个方法可以获取到用户,但是部署到服务器上就不可以了,发现这个auth:api没有起作用,整了一个下午,请指教,本地是Homestead,服务器端是Centos+Apache
@王举 请问如果跨域怎么处理,我现在是在和你类似的响应封装里添加的头部
外加 barryvdh/laravel-cors 这个包(不用没法跨域)
单纯用这个包,系统在抛异常时就没法跨域 :smile:
想请教你有没有好的跨域处理方案,网上好多都是用 middleware,但是异常时不走 middleware :smile:
@Johnson16 有木有执行passport:install? 部署没问题应该就是这个问题了
@王举 非常感谢回答,找到原因了,是因为服务器上的Apache挂了,卸载重新安装了Nginx后,一切顺溜。:pray:
@江渚之上 系统的异常可以拦截和自己定制的,在文章自定义异常的位置你可以加api跨域设置,不过线上项目正常是不允许系统异常的,有异常可以自己测试修改呀 :stuck_out_tongue_closed_eyes:
@王举 access_token 过期,会抛异常的,这个时候应用就不可以跨域了,在自定义异常处理中拼接跨域响应头 这样真的饿好吗 查了很久 没见过呀 :smile:
@江渚之上 我用的5.5,加了一个middleware,没有遇到你这种情况
middleware
kernel
@王举 我想用我自己新建的用户表,attempt方法这里一直报错,attempt方法只支持默认User模型么 :joy:
@Johnson16 请问你用的是laravel自带的User模型么,我用自己新建的模型表,一到$this->guard('api')->attempt($credentials,$request->has('remember'))就报错,求助
@xuhui
自定义用户表的模型文件要这样写:
多用户表登录参考这篇文章:
教程: Laravel 5.3 多用户表登录
然后看
app/auth.php
文件然后验证的时候
@Johnson16


这张数据表不是通过migrate创建的,是直接同事从之前的项目拉过来的,我感觉这是唯一的区别吧,别的地方我基本都是照做的呀 :joy:
@xuhui 你的Customer模型文件确定是绑定user表吗?你的具体表名是什么?有没有系统自带的users表?
@Johnson16
@Johnson16 是不是必须按照多用户的形式搞下面就可以行的通,我现在准备按照你的重新弄一便
@xuhui 必须按照多用户表的方式去做,应为你这样操作,原生的users表的验证就会被替换
@Johnson16 谢谢指导,我现在重新创建一个项目尝试一下
@Johnson16 大神,多用户表登录搞出来了,也可以正常登录,但是为什么$this->guard('api')->attempt($credentials, $request->has('remember'))调用的还是原本User模型来验证,
原本的表数据完全登录不上去,而且不能使用Auth::guard('api')去调用attempt方法,不然会报错方法不存在 :joy: :joy:
目前在做一个前后端分离的网站,用laravel只做接口,现在不太明白的是,前台用户登录坑定要用账号密码获取token值以便访问登陆后的其他页面,那么没登录的时候,对接口的访问是否也是要带上token的,这个token怎么给予客户端?
@王举
@Alexanderwmc 没登录默认没有token啊,需要授权的接口肯定要禁止访问的呀
@王举
一个下午了 :sob:
请问,中间件验证登录失败后返回的是web登录页面?如何设定返回api提示登录
自问自答一下,
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$accessToken,
],
@王举
这么写有问题啊。 我一直报我上面的错误 我换成文档的那种写法就好了
@王举 哥你这个自定义异常好像也有点问题。token过期后并没有拦截 我这边直接去了我后台的登陆页
这里是把参数验证放在控制器里,如果参数多了,放在控制器就不合适。
新建一个 LoginRequest 也不能返回想要的 json。
请问大家有好的解决方法吗。
@王成涛 可以获取的,在
app/Exceptions/Handler
的 render 方法中拦截ValidationException
即可, 获取你可以处理根据之前的4.自定义返回异常
相关代码这个是我之前的实现
感觉没有dingo➕jwt简单啊
@等车的猪 dingo 感觉体验不是很好,不过jwt确实用着比passport要简单的多,所以项目选用我一般优先选用jwt,只是jwt-auth的文档还是0.5的,1.0目前还都是release版本。
上述的方法中如果未授权返回的结果为什么是如下图,而不是自定义的异常格式
@王举 password 用的扩展包也是jwt
@王举
@王举 楼主个人觉得你登录这块有问题。你那个登录验证不应该存在,passport本身就要对用户信息做验证所以没必要自己验证。如果要自定义验证子段上面的朋友已经给出了答案。重写api守卫的模型方法
@王举 大神我的也是报错
@Johnson16 按你的写法
@scenery 整个问题的确有些蹊跷,我抽空帮你看看
请问api接口多版本控制怎么处理?
@Johnson16 这么耍流氓的么:cry:
@huzhuolei 通过不同的请求头或者请求链接划分呗
比如: 链接
或者类型请求头
@王举 哈哈,别告诉别人哈。
这个地方,需要传一个user_id,关联users表id,如果不绑定user_id,请求获取token会返回:The user credentials were incorrect
您好,我在使用的过程中,发现,laravel中api接口的话,如果设置的独立验证器之类的话。 我们还是需要去针对性的去定制优化。
例如独立验证器具中,我们使用respose的话,直接return, 还是会使用FormRequest的响应规则
所以我在基础上进行修改了一下,您看看怎么样呢?
https://github.com/surest-sky/example/blob...
如果真的是采取官方passport+API Resource+Gates&Policies采取RESTful API的话实现起来可比这简单多了,作者把流程搞复杂了,代码也没有组织好,逻辑上有些乱了。想要用好Passport,OAuth2.0的基础还是要有的,不然授权表里的东西压根都理解不了的。Coding10 的教程里对API的开发讲解的我觉得是解释的最清楚的,虽然是付费的教程
我在想ApiResponse有必要放到这么深的目录下吗,或者有没有其他更好的位置可以放
@被困群众 放到哪无所谓啦,看个人喜好,比如直接放到app下面啥的
@Thank 虽然我不知道你是否还需要,但可以拦截 这个 Dotenv\Exception\ValidationException; 一样可以捕获到验证层的错误
我想问一下,这样处理,很多异常假如不放到doReports中的话,经常会报错500,然后没有任何错误信息,这是我的写法,是否有更好的解决方式呢
比如一个没放在doReport的错误
@mingzaily 我是这么处理的 https://github.com/wowiwj/story-server/blo...
系统错误信息还是比较敏感的,默认不会暴露给前端
@王举 谢谢,我也是第一次碰API,开始看教程用dingp\api,但是相关的异常,根本没有办法重写,把它汉化成中文,又看到你这篇文章,很大的启发
@王举 我找到一个方法了
在env的APP_DEBUG控制是否显示系统错误信息
例子
开启debug
关闭debug
大佬 ,请教下返回资源集合的时候,隐藏个别字段有比较好的方法吗 :grinning:
@lun1bz Api Resource 文档去研究一下,写 Api 神器
@王举 看了好几遍了,没找到合适的办法,返回资源集合我暂时给手动查询返回了,返回单个资源没问题,用了你的这个trait重写了下 :grin:谢谢啦
@王举 请问你做 token 刷新了吗?这里生成的 token 有效期有一年之久,token 一旦被别人拿去了,就很危险了 :smile:
@王举 请问如何增加自定义错误码呢,比如我想返回 1001 和 1002 给前端做额外的操作
请问前端是通过判断code=200还是success来判断此次请求成功。我看code有时会自定义改变
@____
@lun1bz
前端通过 res.code 可以获取状态码,返回 failed()用res.code获取不到需用 res.data.code