I'm new to Yii. I have an issue with authenticating for different locations. I have an app that needs admin and user authentication. While admin uses google auth, users use the de facto username/password combo.
Below is my code. What am I missing. Basically, I want when a user types /admin her/she should get the admin login - which I have sorted and when he/she types /account/login the user should get the regular username/password login.
public function beforeAction($action)
{
$host = $_SERVER ['REQUEST_URI'];
if (!isset(Yii::app()->session['user_type']))
{
if ($host != '/account/login' && $host != '/admin')
{
//header('Location: /access');
header('Location: /account/login');
}
/*else if ($host != '/admin')
{
header('Location: /admin');
}*/
}
else
{
$access = $this->access();
$currentCont = ucfirst($this->getUniqueId());
if (!empty($access))
{
if (!in_array($currentCont, $access))
{
Yii::app()->session->clear();
Yii::app()->session->destroy();
header('Location: /account/login');
}
}
return parent::beforeAction($action);
}
return parent::beforeAction($action);
}
I believe that .htaccess might be translating your requests from 1 to another.
Even if your url might be /admin it might be translating to something else with .htaccess and that is actually your URI.
Either that or I am very tired now :(.
I found a not so elegant solution for this issue:
if ($currentCont != 'admin' && $host != 'login')
{
echo '<meta http-equiv="refresh" content="0; url='.Yii::app()->createUrl('/account/login').'">';
}
else
{
echo '<meta http-equiv="refresh" content="0;url='.Yii::app()->createUrl('/admin').'">';
}
It strikes me as strange you would be doing this with a beforeAction. If I understand your need, I would write two actions. One would be site/login and would handle the regular users and one would be site/admin and would handle your admin users.
I'd have the regular login for your normal users:
public function actionLogin()
{
if (!\Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->goBack();
} else {
return $this->render('login', [
'model' => $model,
]);
}
}
and then I'd have a second action for the admin case.
public function actionAdmin()
{
if (!\Yii::$app->user->isGuest) {
return $this->goHome();
}
<do google auth stuff>
if (<authenticated by google>) {
return $this->goBack();
} else {
<deal with authentication failure>
}
}
Related
I'm doing my website with PHP using CodeIgniter framework.
I have some pages that I want to hide from users, and I just want to do very simple authentication. For example, I just hardcode an ID and a password in my header script, and requires users to enter ID and password to show the contents. Is it possible to do that with CodeIgniter ? Thanks.
You should take a look at the PHP Basic authentification: http://php.net/manual/en/features.http-auth.php
<?php
$user = 'foo';
$pwd = 'bar';
if (!isset($_SERVER['PHP_AUTH_USER']))
{
askForPwd();
}
else
{
if ($_SERVER['PHP_AUTH_USER'] !== $user && $_SERVER['PHP_AUTH_PW'] !== $pwd)
{
askForPwd();
}
// continue execution
}
function askForPwd()
{
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Text to send if user hits Cancel button';
exit;
}
This is as basic as it gets. User wants to go to hidden page 1, if they have no session they are redirected to the login page (just needs a post to itself and an id and password field and a place to echo $msg). Once logged in they will be redirected back to the hidden page and can view contents.
This can be cleaned up a bit, but it is the general idea.
class Auth extends CI_Controller {
private $id = '123';
private $password = 'abc';
public function __construct() {
parent::__construct();
$this->load->library('session');
$this->load->helper('url');
}
public function login_page() {
$data = array();
if ($this->input->post()) {
$id = $this->input->post('id');
$password = $this->input->post('password');
if ($id == $this->id && $password == $this->password) {
$this->session->set_userdata('auth', TRUE);
if ($this->session->has_userdata('redirect_to')) {
redirect($this->session->redirect_to);
exit;
}
// no redirect specified, display message
$data['msg'] = 'Logged in.';
} else {
$data['msg'] = 'Wrong credentials.';
}
}
$this->load->view('login', $data);
}
public function hidden_content_1() {
if (!$this->session->has_userdata('auth')) {
$this->session->set_userdata('redirect_to', uri_string());
redirect('auth/login_page');
}
echo 'If you are seeing this you are logged in!';
}
}
I think you should be a role type related with your user and you can set a role for public users. After that You can check that in your controller Using Codeigniter session. If you share your controller and model. We can help you..
I need to check if a user is existing in the mgrUser table. now the propblem is the controller is in the adminController while the model is in the mgrUserModel. how do i use Auth for this? Thats the reason why I made a generic login code.
public function login() {
// if ($this->Auth->login()) {
// return $this->redirect($this->Auth->redirectUrl());
// }
// $this->Flash->error(
// __('Username ou password incorrect')
// );
//since the model is in a different view, I needed to includ the mgrModel and create a generic login
//will revamp the code to fit the built in Aut code for php cake
if(isset($_POST['submit'])) {
$User_ID = htmlspecialchars($_POST['user_id']);
$Pass = htmlspecialchars($_POST['pass']);
try {
$mgrUserModel = new MgrUser();
$isValid = $mgrUserModel->find('first', array(
'conditions' => array("user_id" => $User_ID)
));
if($isValid != null){
if (($isValid['MgrUser']['pass']) == $Pass) {
//this doesnot work
$this->Auth->allow();
$this->redirect($this->Auth->redirectUrl());
}
else{
}
}
} catch (Exception $e) {
//echo "not logged in";
}
// this echo will show the id and pass that was taken based on the user_id and pass that the user will input
//for testing only
// echo $isValid2['MgrUser']['id'];
// echo $isValid2['MgrUser']['pass'];
}
}
You need double == to compare things,
function checkMe()
{
if($user == 'me'){
$this->Auth->allow('detail');
}
}
what you did was assign "me" string to variable $user which always returns true because assignment was possible
Anyway you should use it in beforeFilter which is running before every action from this controller, which makes much more sense
public function beforeFilter() {
parent::beforeFilter();
if($user == 'me'){
$this->Auth->allow('detail');
}
}
the Auth component could be configured to read the user information via another userModel (The model name of the users table). It defaults to Users.
please consult the book for appropriate cakephp version: https://book.cakephp.org/3.0/en/controllers/components/authentication.html#configuring-authentication-handlers
I have write a custom login functionality in an old fashioned way.
1.If the email or password is incorrect it will shows the correct error message (ie invalid email,invalid password,account blocked)
2.If login is ok set a session user with corresponding row from the user table.
3.redirect to different url's according to usertype
Here is the implementation
public function login(Request $request)
{
$matches=['email'=>$request->email];
$users =User::where($matches)->first();
if($users == FALSE)
{
$request->session()->flash(
'errors',
'Invalid Email');
return redirect('adminlogin');
}
else if($users->account_status==0)
{
$request->session()->flash(
'errors',
'Account is blocked please contact admin');
return redirect('adminlogin');
}
else if (!Hash::check($request->password,$users->user_password))
{
$request->session()->flash('errors', 'Invalid Password');
return redirect('adminlogin');
}
else
{
$request->session()->put('user',$users);
if($users->user_type == 1)
{
$url = 'index';
}
else if($users->user_type == 3)
{
$url = 'index/package-home';
}
else
{
return view('errors.404');
}
return redirect($url);
}
}
Also in every page i've checked the user authentication with session value,if user session is not set it will redirect to login screen.
public function index(Request $request,$page='admin-home',$id=null)
{
if(!$request->session()->has('user'))
{
$request->session()->flash('errors', 'Session is expired');
return redirect('adminlogin');
}
//load dashboard
}
So my question is my method is correct for a custom authentication or do i need to anything else??
Note:
I don't like to use laravel default auth system,because it dosen't provide a way for custom error message or redirect to differnt url's based on usertype (ie admin,super admin etc)
I was trying to redirect after signin in yii framework but its not working i want to redirect to customer/dashboard after signin here's the code i am working
public function actionLogin() {
if (Yii::app()->user->getId() !== null) {
$url = Yii::app()->createUrl('customer/dashboard');
$this->redirect($url);
// $this->redirect(Yii::app()->createUrl('customer/dashboard'));
}
$this->layout = "main";
$model = new LoginForm;
$this->title = "Login";
if (isset($_POST['ajax']) && $_POST['ajax'] === 'login-form') {
echo CActiveForm::validate($model);
Yii::app()->end();
}
// collect user input data
if (isset($_POST['LoginForm'])) {
$model->attributes = $_POST['LoginForm'];
// validate user input and redirect to the previous page if valid
if ($model->validate() && $model->login()) {
// we are now redirecting to the home page after login instead (as
// in update note above). IF the user is not applying for a job.
$url = Yii::app()->createUrl('customer/dashboard');
$this->redirect($url);
// $this->redirect(Yii::app()->createUrl('customer/dashboard'));
} else {
$_SESSION['pageName'] = "/UserEvents/LoginError";
}
}
// display the login form
$this->render('login', array('model' => $model));
}
IN that i am using actionLogin function to login
regards
Change the code Yii::app()->createUrl('customer/dashboard'); to Yii::app()->urlManager->createUrl('customer/dashboard'). Also you can pass an array to redirect() function and Yii will take care of generating correct url $this->redirect(['customer/dashboard']);
If you want to use createUrl function then follow below pattern
$this->redirect(Yii::app()->createUrl('/modulename/controllername/action'));
And If you want to redirect without createUrl then use below one
$this->redirect(array('controllername/action'));
Use this code for redirect.
if (Yii::app()->user->getId() !== null) {
$this->redirect(array("customer/dashboard"));
}
We are using the Auth component. We are currently able to prevent non-logged in users from visiting our "admin" page (adminhome.ctp). But we can't figure out how to make isAuthorized() prevent non-admins from visiting the page also.
Inside the AppController:
public function beforeFilter() {
$this->Auth->allow('index', 'view', 'login', 'logout', 'display');
$this->Auth->authorize = array('Controller');
//$this->Auth->autoRedirect = false;
}
public function isAuthorized($user_id) {
$this->loadModel('User');
$user = $this->User->findById($this->Auth->user());
if ( $user['User']['role'] === 'admin') {
$this->Session->setFlash('isAuthorized');
return true;
}
$this->Session->setFlash('!isAuthorized');
return false;
}
Here the beforeFilter() in PagesController:
function beforeFilter() {
$this->Auth->deny('adminhome');
}
What are we doing wrong?
I have just used Aryan answer however I have made some minor changes which could be helpful for others:
if($this->Session->read('Auth.User.role') != 'admin')
{
$this->Session->setFlash('You are not authorized to visit this page');
$this->redirect('/');
}
I believe that your way it doesn't work because you should use Auth->deny() to restrict access to methods, and adminhome is not a method in the PagesController. Try this:
# in app/controller/PagesController.php
public function display() {
$page = empty($this->request->params['pass'][0]) ? null : $this->request->params['pass'][0];
if($page == 'adminhome' || $this->User->isAuthorized()) {
$this->render($page);
} else {
# redirect the user somewhere else
}
}
I hope this helps
You'll have role field in user table. In particular action add this line
if($this->Session->read('Auht.User.role') != 'admin') {
...............................
}
If you want only admin can see every actions in some controller like admincontroller
you can add this code in that controller in beforeRender action
if($this->Session->read('Auth.User.role') != 'admin')
{
$this->Session->setFlash(You are not authorized to visit this page,'flash',array('alert'=>'info'));
$this->redirect('/');
}