I'm building a little Lumen application with a simple API & Authentication.
I want to redirect the user to the intended URL and if he visits /auth/login by himself I want him to redirect to /foo.
In the Laravel Docs there is this function: return redirect()->intended('/foo');
When I use this in my route I get an error in the server log which says this:
[30-Apr-2015 08:39:47 UTC] PHP Fatal error: Call to undefined method Laravel\Lumen\Http\Redirector::intended() in ~/Sites/lumen-test/app/Http/routes.php on line 16
I think this is because Lumen is a smaller version of Laravel and maybe this function isn't implemented (yet).
I solved this problem by adjusting my Middleware a little bit as well as storing the Request::path() in the session.
This is how my Middleware looks:
class AuthMiddleware {
public function handle($request, Closure $next) {
if(Auth::check()){
return $next($request);
} else {
session(['path' => Request::path()]);
return redirect('/auth/login');
}
}
}
And in my routes.php I have this route (which I will outsource to a controller asap):
$app->post('/auth/login', function(Request $request) {
if (Auth::attempt($request->only('username', 'password'))){
if($path = session('path')){
return redirect($path);
} else {
return redirect('/messages');
}
} else {
return redirect()->back()->with("error", "Login failed!");
}
});
Thanks to IDIR FETT for suggesting the Request::path() method.
Hopefully this will help a few people that are new to
Lumen, which is a great framework by the way. :)
Indeed looking at the source code of Lumen it is not implemented:
https://github.com/laravel/lumen-framework/blob/5.0/src/Http/Redirector.php
Your options are:
Check Laravel's (Symfony's?) implementation and put it into your own code
Write completely your own implementation – one super simple way of doing it would be store the request URL in a session, redirect to the login page and when the user successfully logs in retrieve the URL from the session and redirect him
i think you have to specify a route name in the intended method, not a URI:
return redirect()->intended('foo');
assuming you have already named the route, i think this still works as well:
return Redirect::intended('/foo');
UPDATE:
try this:
retrieve the requested URI :
$uri = Request::path(); // Implemented in Lumen
then redirect to the requested URI :
return redirect($uri);
this could work !!
Related
I'm using Laravel framework my previous version of laravel is 5.8
and in my middleware login
public function handle($request, Closure $next)
{
if(Auth::check())
{
return $next($request);
}
else
{
Session::put('url.intended',URL::previous());
return redirect('/login');
}
}
and this is the controller login controller
if(Session::get('url.intended') <> '')
return Redirect::to(Session::get('url.intended'));
else
return redirect('/');
with this codes in laravel 5.8 everything was working great but when i upgrade to laravel 6 its not working any more i dont know why
any help here thanks
if i came from any link its always redirect me to / link
You should probably be letting the framework handle as much of this as possible. If you must use your own middleware and Controller method still let the framework handle this as it does best.
Dealing with the intended URL is already something the framework is capable of doing itself and checks multiple conditions to figure this out. You can use the guest method of the Redirector to have it do this for you:
return redirect()->guest('login');
This will take care of the redirect to 'login' and set the url.intended in the session as needed.
After login is successful you can redirect them to where they were trying to end up, 'intended', or a fallback url:
return redirect()->intended('/');
This will redirect to what it can find as the 'intended' and if not use a fallback. It will also remove the 'url.intended' key from the session as it is no longer of use. No need to set or check the session yourself.
I'm writing a server based solution. In database there are many users with different permissions and I have to check if they have permission to access module they are trying to.
In every Controller I have included something like:
protected $module = "moduleName";
I tried to solve it like:
function __construct()
{
$perm = session()->get('perm');
if (!isset($perm[$this->module]) || !$perm[$this->module]) {
Session::flash('message_error', "<span class='glyphicon glyphicon-warning-sign'></span> Access denined!");
return back();
}
}
It shows the message but it still displays the page not redirects back.
As you see I'm reading permissions from session and modules name is saved in controller so I don't think this could be solved by middleware unless I'm making middleware for each module (I'm talking about 30 modules).
Thanks for taking the time to read this
Middleware actually solved this.
Route:
Route::group(['middleware' => 'module:moduleName'], function () {
// Routes...
});
Custom middleware:
public function handle($request, Closure $next, $module)
{
$perm = session()->get('perm');
if (!isset($perm[$module]) || !$perm[$module]) {
Session::flash('message_error', "<span class='glyphicon glyphicon-warning-sign'></span> Access denined!");
return redirect()->back();
}
return $next($request);
}
Also I'll mention that Route groups can be nested. So you can wrap multiple groups with something like auth middleware as well
There is a very easy fix to your code, you forgot the define the redirect, so instead of using
return back();
use
return redirect()->back();
This will do the redirect.
There is also a mistake in your reasoning, you could and probably should use middleware.
Middleware does have access to the user, session and can be passed parameters. These are the necessary requirements for your system.
You can also assign middleware on a controller basis.
Brief:
Actually, I'm little bit confused while using Laravel api route file.
Question:
If I need to access the data of my web site in other platform (like android app) that is made using laravel, then should I create a different route in api.php file?
If yes then I will be declaring two routes and controllers for each request, first in web.php and second in api.php. Is it correct?
Basically, I want to ask that how I can make an api, so that I can access the data in website as well as in other platforms?
I was searching for a good tutorial for this, but I didn't got a good one.
Ideally the API routes and Web routes should be completely different but if you want it to be same then instead of defining routes in different file you can add routes only in web.php and add a special parameter from your client and in controller if you are getting the parameter then return the JSON Object or else return the view.
Eg.
web.php
Route::get('getUsers','UserController#getUsers');
UserController.php
...
public function getUsers(Request $request)
{
...
if ($request->has('api')) {
return $users; //API Route (Laravel will by Default return the JSON Response no need to do json_encode)
}
return view('pages.user_list'); //Normal Routes hence returning View
}
...
Requests
Normal Request
<Yourdomain>/getUsers
API Request
<Yourdomain>/getUsers?api=true
I hope that helped...
Write your api routes in api.php and web routes in web.php.
The Api routes always have the name api in the routes thus you can differentiate the routes., I mentioned here because as #Akshay Khale mentioned an example with query parameter.
if you want to use the same controller for both API and Web, Api Requests always have the Header Content-Type : Json and "Accept":"application/json" so in your controller you can do it as below.
public function getUsers(Request $request)
{
...
if ($request->wantsJson()) {
return response()->json($users, 200); //here why we are extending response object because using json() method you can send the status code with the response.
}
return view('pages.user_list'); //Normal Routes hence returning View
}
for the laravel 5.6 and above the above answers won't work for me , so here is my 2 cents.
I have put the routes in web.php and api.php and normal no any magic tricks .
public function getUsers(Request $request)
{
....
if( $request->is('api/*')){
...
return response()->json($user_data, 200);
}
...
return view('users', ['users_data'=>$user_data]);
}
It will return json output for
127.0.0.1:8000/api/users
and normal view in html for
127.0.0.1:8000/users
I am using a session separately other than the default authentication sessions. If an user try to access my secured page, he should have the session set. If anyone without that session try to access means, they will be redirected to error page. I am using Laravel 5.3
The user can view the below two pages only if the session variable named 'secured_user' is set. Otherwise they will be redirect to the error page
Route::get('/secured-page1', 'ValidationController#CheckSecuredLogin_1');
Route::get('/secured-page2', 'ValidationController#CheckSecuredLogin_2');
The best option would be a policy.
You can create certain constrains and couple it with your models. Policies are especially suitable for changing your logic later on.
See here: Create Policy
Within you PagesPolicy, you can add this function:
public function before(User $user, $ability)
{
if ($user->isSuperAdmin()) {
return true;
}
}
public function seeSecurePage(User $user)
{
// Your custom Code and session handling
if(session("secured_user")) return true;
return false;
}
and in your controller.
$user->can("seeSecurePage","Pages");
If "can" fails, it will automatically redirect to error 403.
P.S.: Another possibility are Gates
You should use Laravel Middlewares to achieve this, I think middlewares are made for the work you need:
First create a new middleware by running the artisan command:
php artisan make:middleware CheckSesison
Then the CheckSession would look like this:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckSession
{
public function handle($request, Closure $next)
{
if ($session_value != 'YOUR_DESIRED_VALUE') {
return redirect('home');
}
return $next($request);
}
}
Now in your routes file you can use laravel's route middleware() method to implement it like this:
Route::get('/secured-page1', 'ValidationController#CheckSecuredLogin_1')
->middleware(CheckSession::class);
Hope this helps!
In addition to the awnser above, you could also use middleware that's used on the routes and even group them if required. It is a simple, quick and clean solution. Inside the middelware you simple check if the session you require is there and depending on the result you take any action necessary.
Laravel middleware docs
I create REST API using Laravel. And i am is in Login API, so i use AuthController built it from Laravel.
But, when i authenticate user login using Auth::attempt() in the first time i successfully get User Info cause i call this method Auth::user().
But, when i run again in second time, i get this following Error :
NotFoundHttpException in RouteCollection.php line 161:
I know it send redirect automatically if user has authenticated. And save the session.
Here is my Login Code in AuthController.php
public function demo() {
if (Auth::attempt(Input::only('email','password'))) {
return Auth::user();
} else {
return "false";
}
}
And i write the routes like this :
Route::post('demo', 'Auth\AuthController#demo');
How to disable redirect in that case?
Cause i wanna call my API from my mobile application.
Thank you
Answer
Okay i get the solution, but it's not elegant way. I edit the class
RedirectIfAuthenticated and remove return redirect(/home) in
handle method.