Authentication laravel can't work on my program. I have googled but not solve this. My program is
LoginController#auth
public function auth()
{
$username = Input::get('username');
$password = Input::get('pass');
if(Auth::attempt(array('id' => $username, 'password' => $password)))
{
echo "Work";
}
else
{
echo "Bad";
}
}
Authtable.php
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class Authtable extends Eloquent implements UserInterface, RemindableInterface
{
protected $table = 'authtable';
protected $hidden = array('password');
/**
* Get the unique identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifier()
{
return $this->getKey();
}
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->password;
}
/**
* Get the e-mail address where password reminders are sent.
*
* #return string
*/
public function getReminderEmail()
{
return $this->email;
}
public function getRememberToken()
{
return $this->remember_token;
}
public function setRememberToken($value)
{
$this->remember_token = $value;
}
public function getRememberTokenName()
{
return 'remember_token';
}
}
auth.php
'driver' => 'eloquent',
'model' => 'Authtable',
'table' => 'authtable',
And nullable remember_token(varchar(100)), password(varchar(60)) but still not work. Please give some solution.
I had a bad experience about that.
Composer dump-autoload to make sure model name is working.
Check that model name has no conflicts
Check 'authtable' column names. Is that columns include what you Input?'id' => $username, 'password' => $password
Related
I just checked using dd() that my variable $username and $password are not null.
But why Auth::attempt($user) is always return error message Undefined index: password
LoginController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
public function index()
{
return view('login/index', [
'title' => 'LOGIN'
]);
}
public function authenticate(Request $request)
{
$hashed_password = hash(config('var.default_hash'), $request['password']);
$request['password'] = $hashed_password;
$request->validate([
'username' => ['required'],
'password' => ['required'],
]);
$user = [
'username' => $request['username'],
'password_hash' => $request['password']
];
if (Auth::attempt($user)) {
$request->session()->regenerate();
return redirect()->intended('/');
}
return back()->with('fail', 'Login fail');
}
}
User.php
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class User extends Model implements Authenticatable
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['name', 'username', 'password_hash', 'lang'];
/**
* The column name of the "remember me" token.
*
* #var string
*/
protected $rememberTokenName = 'remember_token';
/**
* Get the name of the unique identifier for the user.
*
* #return string
*/
public function getAuthIdentifierName()
{
return $this->getKeyName();
}
/**
* Get the unique identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifier()
{
return $this->{$this->getAuthIdentifierName()};
}
/**
* Get the unique broadcast identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifierForBroadcasting()
{
return $this->getAuthIdentifier();
}
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->password_hash;
}
/**
* Get the token value for the "remember me" session.
*
* #return string|null
*/
public function getRememberToken()
{
if (!empty($this->getRememberTokenName())) {
return (string) $this->{$this->getRememberTokenName()};
}
}
/**
* Set the token value for the "remember me" session.
*
* #param string $value
* #return void
*/
public function setRememberToken($value)
{
if (!empty($this->getRememberTokenName())) {
$this->{$this->getRememberTokenName()} = $value;
}
}
/**
* Get the column name for the "remember me" token.
*
* #return string
*/
public function getRememberTokenName()
{
return $this->rememberTokenName;
}
}
2021_09_24_081907_create_users_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('username');
$table->text('password_hash');
$table->String('lang');
$table->timestamp('created_at')->useCurrent();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
I think you should create an array like this
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
// Authentication was successful...
}
you need to change the username to email
then password_hash to password and you need to change your database user table.
https://laravel.com/docs/8.x/authentication#authenticating-users
I'm currently using Laravel with Infyom to build a backend, one thing that I'm not understanding is how to have multiple rules for validation depending on the API route, for instance, when I'm creating a user, both fields email and role should be provided to the endpoint, but when updating the user (due to login), only the email and password is required to be present. What I want is to have a different set o rules depending on the endpoint being used, is that possible and how? Currently, the endpoint always returns
{
"message": "The given data was invalid.",
"errors": {
"role": [
"The role field is required."
]
}
}
my routes/api.php looks like this
<?php
use Illuminate\Http\Request;
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::post('login', 'TokenAPIController#loginUser');
Route::put('login/updateToken/{id}', 'TokenAPIController#updateToken');
Route::resource('users', 'UserAPIController');
Route::resource('roles', 'RoleAPIController');
Route::resource('roles', 'roleAPIController');
Route::resource('product_variants', 'Product_variantAPIController');
Route::resource('product_images', 'Product_imageAPIController');
Route::resource('product_categories', 'Product_categoryAPIController');
Route::resource('products', 'ProductAPIController');
Route::resource('orders', 'OrderAPIController');
Route::resource('order_products', 'Order_productAPIController');
Route::resource('notifications', 'NotificationAPIController');
Route::resource('factories', 'FactoryAPIController');
Route::resource('statuses', 'StatusAPIController');
My user app/Models/User.php
<?php
namespace App\Models;
use Eloquent as Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model
{
use SoftDeletes;
public $table = 'users';
const CREATED_AT = 'created_at';
const UPDATED_AT = 'updated_at';
protected $dates = ['deleted_at'];
public $fillable = [
'name',
'role',
'email',
'password',
'remember_token',
'notification_token',
'factory',
'api_token'
];
/**
* The attributes that should be casted to native types.
*
* #var array
*/
protected $casts = [
'id' => 'integer',
'name' => 'string',
'role' => 'integer',
'email' => 'string',
'password' => 'string',
'remember_token' => 'string',
'notification_token' => 'string',
'factory' => 'integer',
'api_token' => 'string'
];
/**
* Validation rules
*
* #var array
*/
public static $rules = [
'role' => 'required',
'email' => 'required'
];
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
**/
public function role()
{
return $this->belongsTo(\App\Models\Role::class, 'role');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
**/
public function factory()
{
return $this->belongsTo(\App\Models\Factory::class, 'factory');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
**/
public function orders()
{
return $this->hasMany(\App\Models\Order::class, 'customer');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
**/
public function order1s()
{
return $this->hasMany(\App\Models\Order::class, 'responsible');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
**/
public function notifications()
{
return $this->hasMany(\App\Models\Notification::class, '"from"');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
**/
public function notification2s()
{
return $this->hasMany(\App\Models\Notification::class, '"to"');
}
}
And finally, my TokenAPIController.php
<?php
namespace App\Http\Controllers\API;
use App\Http\Requests\API\CreateUserAPIRequest;
use App\Http\Requests\API\UpdateUserAPIRequest;
use App\Models\User;
use App\Repositories\UserRepository;
use Illuminate\Http\Request;
use App\Http\Controllers\AppBaseController;
use Response;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Hash;
class TokenAPIController extends AppBaseController
{
/** #var UserRepository */
private $userRepository;
public function __construct(UserRepository $userRepo)
{
$this->userRepository = $userRepo;
}
public function loginUser(UpdateUserAPIRequest $request)
{ /** #var User $user */
$input = $request->all();
if (!isset($input['email'])) {
return $this->sendError('Email is required');
}
if (!isset($input['password'])) {
return $this->sendError('Password is required');
}
$user = User::where('email', $input['email'])
->first();
if (empty($user)) {
return $this->sendError('User not found');
}
$validCredentials = Hash::check($input['password'], $user["password"]);
if ($validCredentials) {
return $this->updateToken($user["id"]);
}
return $this->sendError('No match');
}
public function updateToken($id)
{
// $input = $request->all();
/** #var User $user */
$user = $this->userRepository->find($id);
if (empty($user)) {
return $this->sendError('User not found');
}
$token = Str::random(60);
$user->forceFill([
'api_token' => hash('sha256', $token),
])->save();
return $this->sendResponse($user->toArray(), 'User updated successfully');
}
}
Edit your App\Http\Requests\API\UpdateUserAPIRequest file and adjust the rules it returns from rules.
i have setup a Laravel project with two guards wach with Hi own users table. Now i want to save the sessions into the database instead in a file. The Problem is that I cant save the session in a single table, because the user ID is not unique.
How can I solve this problem? Thanks.
I tried this. This working, but it exists a default session driver, so a user has a session in the default table and in the admin_sessions table.
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
Administrator::class => UserPolicy::class,
];
public function boot()
{
$this->registerPolicies();
Auth::extend('admin_session', function ($app, $name, array $config) {
$provider = Auth::createUserProvider($config['provider']);
$guard = new SessionGuard($name, $provider, $app->session->driver('admin_database'));
if (method_exists($guard, 'setCookieJar')) {
$guard->setCookieJar($this->app['cookie']);
}
if (method_exists($guard, 'setDispatcher')) {
$guard->setDispatcher($this->app['events']);
}
if (method_exists($guard, 'setRequest')) {
$guard->setRequest($this->app->refresh('request', $guard, 'setRequest'));
}
return $guard;
}
}
class SessionServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
}
/**
* Perform post-registration booting of services.
*
* #return void
*/
public function boot()
{
$this->app->session->extend('admin_database', function ($app) {
$table = 'administrator_sessions';
// This is not workin, because I don't have the user her.
/*if (auth()->user() instanceof Customer) {
$table = 'customer_sessions';
}
else if (auth()->user() instanceof Administrator){
$table = 'administrator_sessions';
}*/
$lifetime = $app['config']['session.lifetime'];
$connection = $app['db']->connection($app['config']['session.connection']);
return new DatabaseSessionHandler($connection, $table, $lifetime, $app);
});
}
}
I am using yii2 advanced template and have many user tables. For example Table_1, Table_2, Table_3. How can I make user authentication on different tables by turns? Like check Table_1: if !authenticated: check Table_2: if !authenticated: check Table_3: if !authenticated: denied?
I don't know how extend multiple User classes:
class User extends ActiveRecord implements IdentityInterface
{
/**
* #inheritdoc
*/
public static function tableName()
{
return '{{%user}}';
}
...
LoginForm class:
<?php
namespace common\models;
use Yii;
use yii\base\Model;
/**
* Login form
*/
class LoginForm extends Model
{
public $username;
public $password;
public $rememberMe = true;
private $_user = false;
/**
* #inheritdoc
*/
public function rules()
{
return [
// username and password are both required
[['username', 'password'], 'required'],
// rememberMe must be a boolean value
['rememberMe', 'boolean'],
// password is validated by validatePassword()
['password', 'validatePassword'],
];
}
/**
* Validates the password.
* This method serves as the inline validation for password.
*
* #param string $attribute the attribute currently being validated
* #param array $params the additional name-value pairs given in the rule
*/
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addError($attribute, 'Incorrect username or password.');
}
}
}
/**
* Logs in a user using the provided username and password.
*
* #return boolean whether the user is logged in successfully
*/
public function login()
{
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
} else {
return false;
}
}
/**
* Finds user by [[username]]
*
* #return User|null
*/
public function getUser()
{
if ($this->_user === false) {
$this->_user = User::findByUsername($this->username);
}
return $this->_user;
}
}
Controller:
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,
]);
}
}
Yes you can do.
In LoginForm.php edit getUser() function as this
public function getUser()
{
if ($this->_user === false) {
$this->_user = User::findByUsername($this->username);
}
//to check if user not found in first table then check in another
if(!$this->_user){
$this->_user = UserTwo::findByUsername($this->username);
}
//you can add more for more tables
return $this->_user;
}
generate UserTwo.php model using Gii and change to following:
<?php
namespace app\models;
use Yii;
use yii\web\IdentityInterface;
use yii\db\ActiveRecord;
class UserTwo extends ActiveRecord implements IdentityInterface
{
public static function tableName()
{
return 'user_two';
}
public static function findIdentity($id)
{
return static::findOne(['id' => $id]);
}
public static function findIdentityByAccessToken($token, $type = null)
{
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}
public static function findByUsername($username)
{
return static::findOne(['username' => $username]);
}
public static function findByPasswordResetToken($token)
{
if (!static::isPasswordResetTokenValid($token)) {
return null;
}
return static::findOne([
'password_reset_token' => $token
]);
}
public static function isPasswordResetTokenValid($token)
{
if (empty($token)) {
return false;
}
$expire = Yii::$app->params['user.passwordResetTokenExpire'];
$parts = explode('_', $token);
$timestamp = (int)end($parts);
return $timestamp + $expire >= time();
}
public function getId()
{
return $this->getPrimaryKey();
}
public function getAuthKey()
{
return $this->auth_key;
}
public function validateAuthKey($authKey)
{
return $this->getAuthKey() === $authKey;
}
public function validatePassword($password)
{
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
}
I tried to implement the User Model and LoginForm Model in Yii basic template to validate user logins. I created a database and connected to it. The database as a table user and fields called username, password, authKey, and acessToken populated with values. Extended the User Model from ActiveRecord and implemented \yii\web\IdentityInterface in order to make the in-built Yii2 functions do their job. Also written this method:
public static function tableName() { return 'user'; }
Every time I try to login it throws -> username or password incorrect, from the validatepassword() in LoginForm Model.
Here is my code:
LoginForm Model:
<?php
namespace app\models;
use Yii;
use yii\base\Model;
/**
* LoginForm is the model behind the login form.
*/
class LoginForm extends Model
{
public $username;
public $password;
public $rememberMe = true;
private $_user = false;
/**
* #return array the validation rules.
*/
public function rules()
{
return [
// username and password are both required
[['username', 'password'], 'required'],
// rememberMe must be a boolean value
['rememberMe', 'boolean'],
// password is validated by validatePassword()
['password', 'validatePassword'],
];
}
/**
* Validates the password.
* This method serves as the inline validation for password.
*
* #param string $attribute the attribute currently being validated
* #param array $params the additional name-value pairs given in the rule
*/
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addError($attribute, 'Incorrect username or password.');
}
}
}
/**
* Logs in a user using the provided username and password.
* #return boolean whether the user is logged in successfully
*/
public function login()
{
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
} else {
return false;
}
}
/**
* Finds user by [[username]]
*
* #return User|null
*/
public function getUser()
{
if ($this->_user === false) {
$this->_user = User::findByUsername($this->username);
}
return $this->_user;
}
}
…and here is my User.php Model:
<?php
namespace app\models;
use yii\db\ActiveRecord;
class User extends ActiveRecord implements \yii\web\IdentityInterface
{
public $id;
public $username;
public $password;
public $authKey;
public $accessToken;
public static function tableName() { return 'user'; }
/**
* #inheritdoc
*/
public static function findIdentity($id) {
$user = self::find()
->where([
"id" => $id
])
->one();
if (!count($user)) {
return null;
}
return new static($user);
}
/**
* #inheritdoc
*/
public static function findIdentityByAccessToken($token, $userType = null) {
$user = self::find()
->where(["accessToken" => $token])
->one();
if (!count($user)) {
return null;
}
return new static($user);
}
/**
* Finds user by username
*
* #param string $username
* #return static|null
*/
public static function findByUsername($username) {
$user = self::find()
->where([
"username" => $username
])
->one();
if (!count($user)) {
return null;
}
return new static($user);
}
/**
* #inheritdoc
*/
public function getId() {
return $this->id;
}
/**
* #inheritdoc
*/
public function getAuthKey() {
return $this->authKey;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey) {
return $this->authKey === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password) {
return $this->password === $password;
}
}
I don't know what else should i do, perhaps it has a problem in validating the password or find the username, in Yii2 debug it shows that is proper connected to the mysql database.
Don't messed with the siteController actionLogin() because it is equal to the advanced template and i think it correct to stay that way.
In short, the below function keeps throwing "Incorrect username or password.":
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addError($attribute, 'Incorrect username or password.');
}
}
}
I don't want to give up, but I'm considering go back to the old Yii1.xx. There I could easily query the database and make a good login system working.
I spent almost 72 hours with this login problem and no solution solved it for the basic Yii2 template.
I don't want to use static $users that came as default in the package.
EDIT 2
siteController.php
<?php
namespace app\controllers;
use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\filters\VerbFilter;
use app\models\LoginForm;
use app\models\ContactForm;
use yii\helpers\url;
class SiteController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['logout'],
'rules' => [
[
'actions' => ['logout'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
],
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
],
];
}
public function actionIndex()
{
return $this->render('index');
}
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->redirect(Url::toRoute(['contacto/index']));
} else {
return $this->render('login', [
'model' => $model,
]);
}
}
public function actionLogout()
{
Yii::$app->user->logout();
return $this->goHome();
}
public function actionContact()
{
$model = new ContactForm();
if ($model->load(Yii::$app->request->post()) && $model->contact(Yii::$app->params['adminEmail'])) {
Yii::$app->session->setFlash('contactFormSubmitted');
return $this->refresh();
} else {
return $this->redirect(Url::toRoute(['contacto/create2']));
}
}
public function actionAbout()
{
return $this->render('about');
}
public function actionSkills()
{
return $this->render('skills');
}
public function actionPortfolio()
{
return $this->render('portfolio');
}
// tradução do site
public function beforeAction($action) {
if (Yii::$app->session->has('lang')) {
Yii::$app->language = Yii::$app->session->get('lang');
} else {
Yii::$app->language = 'us';
}
return parent::beforeAction($action);
}
public function actionLangus(){
Yii::$app->session->set('lang', 'us'); //or $_GET['lang']
return $this->redirect(Url::toRoute(['site/index']));
}
public function actionLangpt(){
Yii::$app->session->set('lang', 'pt'); //or $_GET['lang']
return $this->redirect(Url::toRoute(['site/index']));
}
}
1) Stop creating duplicate questions
2) remove the public declarations of variables bellow.
class User extends ActiveRecord implements \yii\web\IdentityInterface
{
public $id;
public $username;
public $password;
public $authKey;
public $accessToken;
$user->password will be empty because of this. Instead of using a magic method to get the values you are actually declaring them... they will always be empty when you use them.