欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

REST API - Authentication Admins and Users

Hey Guys,

I've been stuck on this for a bit not sure what is the best route to go. I have my admin portal, user portal and a rest api all three are using Laravel. I have my admin portal passing over the username / password via a rest call where I just created my model called Admin. Not sure how I should test the username and password that is passed over to the rest api. I will need to use User for actual Users and not Admins, I have to keep them separated. I would like to authenticate the user via rest return back the admin's information and some method of keeping that user logged in to the admin portal. Any suggestions?

This is my Admin Model

<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;

class Admin extends Authenticatable {
    protected $hidden = ['password'];
    protected $primary = 'id';  
    protected $table = 'admin';
}

Route:

Route::group(array('prefix' => 'v1'), function() {
    Route::resource('admin/authenticate', 'AdminController');
});

Admin Controller

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Validator;
use Auth;

class AdminController extends Controller {
    private $_validator = array(
        'rules' => array(
            'username' => 'required|alpha|max:50|min:4',
            'password' => 'required',
        ),
        'messages' => array(
            'required' => ':attribute is required.',
            'alpha' => 'Only alpha values A-z are allowed.',
            'max' => 'Only a :max characters are allowed.',
            'min' => 'At lease :min characters must be entered.'
        )
    );
    
    /* check to see if the admin user exists */
    public function store(Request $_request) {      
        if(!empty($_request->input()) && is_array($_request->input())){
            $_validate = Validator::make($_request->all(), $this->_validator['rules'], $this->_validator['messages']);
            
            if($_validate->fails()){
                return response()->json(['errors' => $_validate->messages(), 'status' => 401], 200);
            } else {
                $_data = $_request->input();
                
// this is where I'm stuck not sure what to do, currently it just does nothing from what I can tell.
                if(Auth::guard('admin')->attempt(['username' => $_data['username'], 'password' => $_data['password'], 'active' => 1])){
                    error_log('IT WORKED?');
                }
                
                error_log('PROCESS REQUEST');
                error_log(print_r($_data, true));
                die;        
            }
        } else {
            return response()->json(array('error' => array('required' => (!empty($_request->input()) && !is_array($_request->input()) ? 'request not in an array format.' : 'missing required input.')  ), 'status' => 401), 200);
        }
    }
}
Best Answer(As Selected By SukhGill)
bobbybouwmann

You are almost there. You can log in any model that is extending the Authenticatable class using the default auth methods. So you indeed need to have a new guard for admins. After that the user should be logged in and you can redirect the user to the admin panel for example.

Attempt will check if the user is valid with the given credentials. If that is the case it will log the user in. After that you can redirect to your admin dashboard.

Take a look at this for a full example: http://stackoverflow.com/questions/34490600/how-to-use-multi-auth-in-laravel-5-2

bobbybouwmann

You are almost there. You can log in any model that is extending the Authenticatable class using the default auth methods. So you indeed need to have a new guard for admins. After that the user should be logged in and you can redirect the user to the admin panel for example.

Attempt will check if the user is valid with the given credentials. If that is the case it will log the user in. After that you can redirect to your admin dashboard.

Take a look at this for a full example: http://stackoverflow.com/questions/34490600/how-to-use-multi-auth-in-laravel-5-2

 
SukhGill

Thanks for the reply, the route I ended up going was with JWT to create a token.

 
SukhGill

I wanted to drop in an update of what I did. I created two user tables (users and admin).

Admin will be used for the admin portal and Users for everything else.

REST Routes

$_api = app('Dingo\Api\Routing\Router');

$_api->version('v1', function ($_api) {
    $_api->get('/', function() {
        return ['Hello' => 'World'];
    });
    
    // authenticate
    $_api->post('admin/authenticate', 'App\Http\Controllers\AdminController@authenticate');
    $_api->post('admin/user', 'App\Http\Controllers\AdminController@user');
});

REST Admin Controller will return a JWT Token if login is validated again the admin table

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\Response;
use JWTAuth;

use Dingo\Api\Routing\Helpers;
use App\Transformers\AdminTransformer;
use App\Admin;

class AdminController extends Controller {
    use Helpers;    
    
    /* check to see if the admin user exists */
    public function authenticate(Request $_request) {
        $_credentials = $_request->only('username', 'password');
        try {
            \Config::set('auth.providers.users.model', \App\Admin::class);
            if (!$_token = JWTAuth::attempt($_credentials)) {
                return $this->response->array(['error' => 'invalid credentials', 'status' => 401]);
            }
        } catch (JWTException $e) {
            return $this->response->array(['error' => 'could not create your token', 'status' => 500]);
        }
        
        // all good so return the token and admin
        if (!$_admin = JWTAuth::authenticate($_token)) {
            return $this->response->array(['error' => 'user not found', 'status' => 404]);
        }

        return $this->response->array(['token' => compact('_token'), 'admin' => compact('_admin'), 'status' => 404]);
    }
    
    public function logout(Request $_request){
        $this->validate($_request, [
            'token' => 'required'
        ]);
        
        \Config::set('auth.providers.users.model', \App\Admin::class);
        JWTAuth::invalidate($_request->input('token'));
        
        return $this->response->noContent();
    }
    
    public function user(){
        
        try {
            \Config::set('auth.providers.users.model', \App\Admin::class);
            if (!$_admin = JWTAuth::parseToken()->authenticate()) {
                return response()->json(['user_not_found'], 404);
            }
        } catch (\Tymon\JWTAuth\Exceptions\TokenExpiredException $_e) {
            return response()->json(['token_expired'], $_e->getStatusCode());
        } catch (\Tymon\JWTAuth\Exceptions\TokenInvalidException $_e) {
            return response()->json(['token_invalid'], $_e->getStatusCode());
        } catch (\Tymon\JWTAuth\Exceptions\JWTException $_e) {
            return response()->json(['token_absent'], $_e->getStatusCode());
        }
        
        return response()->json(compact('_admin'));
    }
    
    public function getToken(){
        
        \Config::set('auth.providers.users.model', \App\Admin::class);
        $_token = JWTAuth::getToken();
        
        if (!$_token) {
            return $this->response->errorMethodNotAllowed('Token not provided');
        }
        
        try {
            $_refreshed = JWTAuth::refresh($_token);
        } catch (JWTException $_e) {
            return $this->response->errorInternal('Not able to refresh Token');
        }
        
        return $this->response->withArray(['token' => $_refreshed]);
    }
}

Client AdminController - which will trigger the REST call to try to login the admin user, I create a cookie of the JWT Token which we will check for on every request and if it's present then we can access all the routes with the middleware of token

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
use Validator;
use App\Providers\RestServiceProvider;
use Illuminate\Support\Facades\Cookie;

class AdminController extends Controller {
    private $_validator = array(
        'rules' => array(
            'username' => 'required|alpha|max:50|min:4',
            'password' => 'required',
        ),
        'messages' => array(
            'required' => ':attribute is required.',
            'alpha' => 'Only alpha values A-z are allowed.',
            'max' => 'Only a :max characters are allowed.',
            'min' => 'At lease :min characters must be entered.'
        )
    );
    
    public function __construct(){
        //$this->middleware('auth');
    }
    
    public function login(Request $_request){
        $_validate = Validator::make($_request->all(), $this->_validator['rules'], $this->_validator['messages']);
        
        if($_validate->fails()){
            return response()->json(['errors' => $_validate->messages(), 'status' => 400], 200);
        } else if($_request->ajax()) {
            $_data = Input::all();
            
            $_rest = new RestServiceProvider();
            $_response = $_rest->request('POST', '/admin/authenticate', $_data);
            
            if(!empty($_response)){
                if(!empty($_response['error'])){
                    return response()->json(['errors' => $_response['error'], 'status' => 400], 200);
                } else if(!empty($_response['token']) && !empty($_response['token']['_token'])) {
                    Cookie::queue(env('RESTAPI_TOKEN', 'resttoken'), $_response['token']['_token'], 60);
                    return response()->json(['success' => array('redirect'=> 'dashboard'), 'status' => 200], 200);
                } else {
                    return response()->json(['success' => array('redirect'=> '404'), 'status' => 404], 404);
                }
            } else {
                return response()->json(['errors' => array('fatal'=> 'sorry your request has been rejected.'), 'status' => 400], 200);
            }           
        } else {
            return response()->json(['errors' => array('fatal'=> 'sorry your request has been rejected.'), 'status' => 400], 200);
        }
    }
}

Client Routes

Route::get('/', function () {
    return view('home');
});

Route::post('admin/login', 'AdminController@login');

Route::group(['middleware' => 'token'], function () {
    Route::get('/dashboard', function ()    {
        return view('dashboard');
    });
});

AddHeaders - Middleware Token Class

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class AddHeaders
{
    /**
     * 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)
    {
        $_token = $request->cookie(env('RESTAPI_TOKEN', 'resttoken'));
        if (!$_token) {
            return redirect('/');
        }
        
        $request->headers->set('Authorization', "Bearer {$_token}");

        return $next($request);
    }
}

Let me know your thoughts?

 
eduardoborges

I have a problem with Dingo. In Subroutes not works the "Config" to user model.

use \App\Convite;

class ConviteController extends Controller
{
    protected $model;

    function __construct(){
        Config::set('auth.providers.users.model', \App\Aluno::class);
        $this->model = Convite::class;
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return $this->response->array( $this->model::all()->toArray() );
    }

}

and i get

{
  "error": "user_not_found"
}
 

来自  https://laracasts.com/discuss/channels/laravel/rest-api-authentication-admins-and-users

普通分类: