I tried this:
Route::get('/', 'PageController#getIndex');
Route::group(array('before' => 'auth'), function(){
Route::controller('/', 'HomeController');
});
But it is always requiring login.
I want the PageController#getIndex to be called when visiting '/' when logged in, and HomeController (#getIndex) otherwise.
I know I could set up a redirect, but I'd like to just handle it all within routing.
You need to setup your own auth filter
if(!Auth::check()){
return Route::get('/', 'PageController#getIndex');
} else {
Route::controller('/', 'HomeController');
}
Related
I have a ASP.NET Core 2.1 MVC application, and I'm trying to return a separate html view when an exception occurs. The reason for this is that if there are errors, we don't want google to register the redirects to the error page for our SEO (I've omitted development settings to clear things up).
Our startup contained this:
app.UseExceptionHandler("/Error/500"); // this caused a redirect because some of our middleware.
app.UseStatusCodePagesWithReExecute("/error/{0}");
But we want to prevent a redirect, so we need to change the UseExceptionHandler.
I've tried to use the answer from this question like below:
app.UseExceptionHandler(
options =>
{
options.Run(
async context =>
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("sumtin wrong").ConfigureAwait(false);
});
});
But this gives a very ugly page without any styling. Another solution we've tried to use is creating an error handling middle ware, but there we run into the same problem there where we can't add a view.
How can I return a styled view in case of an exception, without redirecting the user?
EDIT: the UseExceptionHandler doesn't cause a redirect, it was caused by a bug in some of our middleware.
How can I return a styled view in case of an exception, without redirecting the user?
You're almost there. You could rewrite(instead of redirect) the path, and then serve a HTML according to current path.
Let's say you have a well-styled sth-wrong.html page in your wwwroot/ folder. Change the code as below:
app.UseExceptionHandler(appBuilder=>
{
// override the current Path
appBuilder.Use(async (ctx, next)=>{
ctx.Request.Path = "/sth-wrong.html";
await next();
});
// let the staticFiles middleware to serve the sth-wrong.html
appBuilder.UseStaticFiles();
});
[Edit] :
Is there anyway where I can make use of my main page layout?
Yes. But because a page layout is a View Feature that belongs to MVC, you can enable another MVC branch here
First create a Controllers/ErrorController.cs file :
public class ErrorController: Controller
{
public IActionResult Index() => View();
}
and a related Views/Error/Index.cshtml file:
Ouch....Something bad happens........
Add a MVC branch in middleware pipeline:
app.UseExceptionHandler(appBuilder=>
{
appBuilder.Use(async (ctx, next)=>{
ctx.Request.Path = "/Error/Index";
await next();
});
appBuilder.UseMvc(routes =>{
routes.MapRoute(
name: "sth-wrong",
template: "{controller=Error}/{action=Index}");
});
});
Demo:
I'm making a login page with redirect function,and the logic following like this:
if I never logged and I enter the url '/home/qiputranscode',it will redirect to
'http://127.0.0.1:8000/#/login?redirect=%2Fhome%2Fqiputranscode'.
then I need to request the server with username and pwd to get token for entry '/home/qiputranscode' page.
but after inputting my username and pwd the url become this:
'http://127.0.0.1:8000/?#/login?redirect=%2Fhome%2Fqiputranscode'
and didn't request the server or redirect to '/home/qiputranscode'.
so, why the url add ? in itself before #.
and what's difference between them, I will be grateful if u gave me any suggestion
the redirect code like this:
router.beforeEach((to, from, next) => {
if (to.matched.some(r => r.meta.requiredAuth)) {
if (store.state.token) {
next()
} else {
next ({
path: '/login',
query: {redirect: to.fullPath}
})
}
} else {
next()
}
});
The part after ? is the query with key=redirect and value=full path
To redirect to the saved path call this after login
this.$router.push({ path: this.$route.query.redirectTo })
And you also need to prevent the default form behavior
<form v-on:submit.prevent ...
Not sure if this is possible, but here it goes.
What I am looking to do is include my "admin" routes as a separate file, only if the user is an admin (therefore a non admin will get a 404 error
routes.php
if( Session::get('user')->is_admin )
require_once('routes-admin.php');
if( Auth::check() )
require_once('routes-user.php');
Route::get('/', function() {
return view('home');
});
routes-admin.php
Route::get('admin', function() {
return view('admin-dashboard');
});
routes-user.php
Route::get('user', function() {
return view('user-dashboard');
});
What I am trying to do is avoid having the test repeated with every single Route
so if my user segment has 10 pages I currently need 30 lines of code dedicated to Auth::check() (the if, else and redirect if not), where I can instead have a single check on routes.php and the user will get a 404 if they don't belong
Is there a way to perform this check outside of the Route?
Perhaps you want to read documentation first?
Route::group(['middleware' => 'auth'], function()
{
Route::get('/', function()
{
// Uses Auth Middleware
});
Route::get('user/profile', function()
{
// Uses Auth Middleware
});
});
Above code does exactly what you need, is "person logged in?" let him go to page "whatever".
You can create middlewares (check if user is admin or basic user) yourself and apply on groups.
Example middleware
class BeforeMiddleware implements Middleware
{
public function handle($request, Closure $next)
{
// Perform action
return $next($request);
}
}
Do not get me wrong, just your approach is really not Laravel like. Try to see some open source projects done in L5 or even in L4. Try to use everything Taylor already done for you. Documentation is your firend here.
Following the response of #Kyslik for the middleware, you can "include" your own routes file in your RouteServiceProvider like the default routes file, the RouteServiceProvide is located in: app/Providers/RouteServiceProvider.php,
Find the section
require app_path('Http/routes.php');
and just replicate with the name of your routes file want to include
I am logging in the system successfully but
I want that the user whose role is 'Administrator' can only go to all the routes and user having role as 'Manager' can go to 'Home' and 'GetDocumentDetails' else the other login users will be restricted to home page and the guest to Login page.
My route and filter files are as follows:
Routes:
Route::post('/login', function()
{
$user = array(
'username' => Input::get('username'),
'password' => Input::get('password'));
// verify user credentials
if (Auth::attempt($user,true))
{
$role= Auth::user()->userrole;
return Redirect::route('home');
}
}
// Route for getting document details using get method
Route::get('GetDocumentDetailsById',array('as'=>'GetDocumentDetailsById','uses'=>'DocumentController#GetDocumentDetailsById'));
// Route for guest user
Route::filter('guest', function()
{
if (Auth::check())
return Redirect::route('home')->with('flash_notice', 'You are already logged in!');
// Redirect Log-in user to his home page
});
Filters:
/* Filter to redirect guest user to login page */
Route::filter('auth', function()
{
$role=Auth::user();
if (Auth::guest()) return Redirect::guest('login');
});
Route::filter('auth.basic', function()
{
return Auth::basic('username');
});
Route::filter('guest', function()
{
if (Auth::check()) return Redirect::to('/');
});
I would recommend using Zizaco's Entrust and Confide packages for this purpose, as they greatly simplify this task.
Follow the tutorials on these pages after installing both packages, and then you can limit access to certain routes just by defining Route Permission filters or regular Route filters. No need for any additional logic in controller actions.
These Route Permission filters can easily be defined like this:
// Any route under admin is only accessible by users with role Admin.
// Redirect happens if user doesn't have this role.
Entrust::routeNeedsRole('admin*', 'Admin', Redirect::to('/'));
A Route filter based on permissions would look like this:
Route::filter('myFilter', function()
{
if (!Entrust::can('get_document_details') )
{
return Redirect::to('/');
}
});
This filter could then be applied to any route. See the Entrust documentation for more examples and features. Entrust is really versatile.
I'm using node.js with Express and connect-auth to authenticate users.
This is the verification when requesting /index:
if(req.isAuthenticated()) {
res.redirect('/dashboard');
} else {
res.render('index', { layout: 'nonav' });
}
However, after logging out and going back to f.e. '/dashboard', I can see the dashboard.
How can I put the authentication check to every request to make sure there's a valid user at all times?
Update
I don't have any problems with the authentication, everything works fine! I need a solution which checks every route/request if there's a valid user, without putting a function or if-statement in the route-implementation, as the whole App needs a valid user anyway. The Express-Authentication-Example uses "restrict" in the route-definition, which is close, but with many routes it can easily be forgotten.
app.all('*',function(req,res,next){
if(req.isAuthenticated()){
next();
}else{
next(new Error(401)); // 401 Not Authorized
}
});
// NOTE: depending on your version of express,
// you may need to use app.error here, rather
// than app.use.
app.use(function(err,req,res,next){
// Just basic, should be filled out to next()
// or respond on all possible code paths
if(err instanceof Error){
if(err.message === '401'){
res.render('error401');
}
}
});
If you define the all route before routes which require authentication and after routes which do not (such as the home page, login, etc) then it should only affect the routes that need it. Alternatively you could use a RegExp instead of '*', which would include a subpath or list of paths that require authentication.
Another option would be to create a function to include in each route that requires auth:
function IsAuthenticated(req,res,next){
if(req.isAuthenticated()){
next();
}else{
next(new Error(401));
}
}
app.get('/login',function(req,res,next){
res.render('login');
});
app.get('/dashboard',IsAuthenticated,function(req,res,next){
res.render('dashboard');
});
app.get('/settings',IsAuthenticated,function(req,res,next){
res.render('settings');
});
You can use sessions mechanism provided by connect. Put this code in app.configure() to enable it:
app.use(express.cookieParser());
app.use(express.session({
secret: 'some string used for calculating hash'
}));
After that, you′ll be able to use req.session object (different for each request) to store your authentication data (or anything else). So, your example code will look something like this:
if (req.session && req.session.authorized) {
res.redirect('/dashboard');
}
else {
res.render('index', {layout: 'nonav'});
}
And authentication will look like this:
req.session.authorized = checkPassword(login, passw);
Logout:
req.session.destroy();
More info can be found here.
Another way is to app.use a middleware function. (Example in CoffeeScript.)
# middleware
authKick = (req, res, next) ->
if not do req.isAuthenticated then return res.redirect '/login'
return do next
# apply
app.use authKick
This will work on each request without having to touch the routes.