简体   繁体   中英

Guest users in laravel authorization policies

I use policies for user authorization. How to use policies for guest users?

Here is my code:

In controller:

class PostController extends Controller
{
    public function index(Post $post)
    {
        $this->authorize($post);
        return $post->all();
    }
}

In policy:

class PostPolicy
{
    // This function executes only for authenticated users.
    // I want to use it for guest users too
    public function index(User $user)
    {            
        return $user->can('get-posts');
    }
}

First make a new service provider:

php artisan make:provider GuestServiceProvider

Then edit GuestServiceProvider.php with this:

public function boot()
{
    // Laravel policies only work if the user isn't null so for guest access we need to assign a dummpy user.
    // From now on to check for guest use is_null(Auth::user()->getKey())
    if(!Auth::check()) {
        $userClass = config('auth.providers.users.model');
        Auth::setUser(new $userClass());
    }
}

Now Policies will work for guest users and in your policy you can check for the guest by doing:

if(is_null(Auth::user()->getKey())){
    // it's a guest
}

Which essentially means if the user doesn't have an id then its not a real user, hence must be a guest.

Laravel 5.7 now has this feature built in (with PHP >=7.1) See the docs on the new Gate . For anyone using older versions, here is my solution. Make a small helper to use the authorizeForUser method on Illuminate\\Foundation\\Auth\\Access\\AuthorizesRequests . It leaves all native functionality intact. Extend your controller:

use App\User;

public function authorizeAnyone($ability, $arguments = []) {
   list($ability, $arguments) = $this->parseAbilityAndArguments($ability, $arguments);
   return $this->authorizeForUser( auth()->user() ?? new User(), $ability, $arguments);
}

Then wherever you want the possibility of checking your policy against a guest, use

$this->authorizeAnyone();

instead of

$this->authorize();

If you don't want to extend your controller, you can also call (for example):

$this->authorizeForUser( auth()->user() ?? new User, 'index', $post );

In your PostPolicy change this

class PostPolicy{
// This function executes only for authenticated users.
// I want to use it for guest users too
public function index(User $user)
{            
    return $user->can('get-posts');
}
}

to:

class PostPolicy{
// This function executes only for authenticated users.
// I want to use it for guest users too
public function index(?User $user)
{            
    return $user->can('get-posts');
}
}

source

I think the simpliest way is to protect with Auth middleware. or check if user is authenticated in policy

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM