custom auth and hashing laravel 5.1 - php

I have an existing database.
users :
username => varchar
password => md5 hashing
I am new to laravel, I was try to create simple login and register from laravel docs, thats work fine,
but in docs are create for laravel,
now I want to create same login/register but with existing datas.
I was read some Question from How to use SHA1 encryption instead of BCrypt in Laravel 4?
but I dont understand how to use it.
any adv?
sory for my bad grammer.

I'll Try to answer my question.
I take it from Facebook Group Laravel Indonesia
Create directory app/libraries
Add app/libraries to composer.json
"classmap": ["database","app/libraries"],
Create MD5Hasher.php in app/libraries
<?php
namespace App\Libraries;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
class MD5Hasher implements HasherContract {
public function make($value, array $options = array()) {
$value = env('SALT', '').$value;
return md5($value);
}
public function check($value, $hashedValue, array $options = array()) {
return $this->make($value) === $hashedValue;
}
public function needsRehash($hashedValue, array $options = array()) {
return false;
}
}
Create MD5HashServiceProvider.php in app/libraries
<?php
namespace App\Libraries;
use Illuminate\Support\ServiceProvider;
class MD5HashServiceProvider extends ServiceProvider {
/**
* Register the service provider.
*
* #return void
*/
public function register() {
$this->app['hash'] = $this->app->share(function () {
return new MD5Hasher();
});
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides() {
return array('hash');
}
}
in config/app.php
Find Illuminate\Hashing\HashServiceProvider::class,
Change to App\Libraries\MD5HashServiceProvider::class,
in AuthController.php
Add protected $username = 'username';
return Validator::make($data, [
//'name' => 'required|max:255',
'username' => 'required',
'password' => 'required|confirmed|min:5',
]);
return User::create([
//'name' => $data['name'],
'username' => $data['username'],
'password' => md5($data['password']),
]);
in App\Users.php
Change protected $fillable = ['name', 'email', 'password'];
To protected $fillable = ['username', 'password'];
Don't forget to run composer dumpautoload
I don't know what I am doing is right or not.
Regard

Related

Why Laravel Auth::guard()->attempt() isn't working?

So basically I generate users data after a payment, which it is saved in a table I created, it has a username and a encrypted password with Hash::make() method.
What I wanna do is to login with that data stored in the DB, so I made a guard.
This is the auth.php file with guards:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'plataforma' => [
'driver' => 'session',
'provider' => 'usuario',
],
],
And these are the providers:
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'usuario' => [
'driver' => 'eloquent',
'model' => App\Models\Usuario::class,
],
This is the model:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Usuario extends Authenticatable
{
use HasFactory;
use Notifiable;
protected $guard = 'plataforma';
protected $fillable = [
'nombre_usuario', 'correo', 'clave',
];
protected $hidden = [
'clave', 'remember_token',
];
}
And finally the controller:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
class PlataformaController extends Controller
{
public function login()
{
return view('web.plataforma-login');
}
public function autenticar(Request $request)
{
if (Auth::guard('plataforma')->attempt(['nombre_usuario' => $request->input('nombre_usuario'), 'clave' => $request->input('clave')])) {
return view('web.plataforma');
} else {
dd(Auth::guard('plataforma')->attempt(['nombre_usuario' => $request->input('nombre_usuario'), 'clave' => $request->input('clave')]));
}
}
public function dashboard()
{
return view('web.plataforma');
}
}
So basically the Auth::guard('plataforma')->attempt(...) returns false, I already checked that the values of $request->input(...) are correct, I checked that the encrypted password in the DB is the same as the password that the user enter with Hash::check(), so I don't know what is wrong and I'm so confused...
I spent a lot of time reading other questions with no solutions either, I would be glad if anyone can help me out.
After reading the API, I've come to the conclusion attempt() is not working to you because you're using a different password column name.
The following is the attempt function's code from the Illuminate\Auth\SessionGuard class:
/**
* Attempt to authenticate a user using the given credentials.
*
* #param array $credentials
* #param bool $remember
* #return bool
*/
public function attempt(array $credentials = [], $remember = false)
{
$this->fireAttemptEvent($credentials, $remember);
$this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);
// If an implementation of UserInterface was returned, we'll ask the provider
// to validate the user against the given credentials, and if they are in
// fact valid we'll log the users into the application and return true.
if ($this->hasValidCredentials($user, $credentials)) {
$this->login($user, $remember);
return true;
}
// If the authentication attempt fails we will fire an event so that the user
// may be notified of any suspicious attempts to access their account from
// an unrecognized user. A developer may listen to this event as needed.
$this->fireFailedEvent($user, $credentials);
return false;
}
The key functions here are retrieveByCredentials and hasValidCredentials
Here's retrieveByCredentials from Illuminate\Auth\EloquentUserProvider. As you can see, it's excluding the 'password' key from the query in the foreach.
/**
* Retrieve a user by the given credentials.
*
* #param array $credentials
* #return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveByCredentials(array $credentials)
{
if (empty($credentials) ||
(count($credentials) === 1 &&
→ Str::contains($this->firstCredentialKey($credentials), 'password'))) { ←
return;
}
// First we will add each credential element to the query as a where clause.
// Then we can execute the query and, if we found a user, return it in a
// Eloquent User "model" that will be utilized by the Guard instances.
$query = $this->newModelQuery();
foreach ($credentials as $key => $value) {
→ if (Str::contains($key, 'password')) { ←
continue;
}
if (is_array($value) || $value instanceof Arrayable) {
$query->whereIn($key, $value);
} elseif ($value instanceof Closure) {
$value($query);
} else {
$query->where($key, $value);
}
}
return $query->first();
}
Here's hasValidCredentials from Illuminate\Auth\EloquentUserProvider. The key function here is validateCredentials
/**
* Determine if the user matches the credentials.
*
* #param mixed $user
* #param array $credentials
* #return bool
*/
protected function hasValidCredentials($user, $credentials)
{
$validated = ! is_null($user) && $this->provider->validateCredentials($user, $credentials);
if ($validated) {
$this->fireValidatedEvent($user);
}
return $validated;
}
Here's validateCredentials from the Illuminate\Auth\EloquentUserProvider class. You can see it's again, using by default 'password' as the key name. Let's see what getAuthPassword() looks like.
/**
* Validate a user against the given credentials.
*
* #param \Illuminate\Contracts\Auth\Authenticatable $user
* #param array $credentials
* #return bool
*/
public function validateCredentials(UserContract $user, array $credentials)
{
→ $plain = $credentials['password']; ←
return $this->hasher->check($plain, $user->getAuthPassword());
}
And finally getAuthPassword from the Illuminate\Auth\Authenticatable class. It's just returning the model's 'password' attribute.
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
→ return $this->password; ←
}
Basically, if you want this to work, you need to change a few things about your code.
Use password as the key in attempt()
public function autenticar(Request $request)
{
$attempt = Auth::guard('plataforma')->attempt([
'nombre_usuario' => $request->input('nombre_usuario'),
'password' => $request->input('clave')
]);
if ($attempt) {
return view('web.plataforma');
} else {
dd($attempt);
}
}
Override your Authenticatable model (Usuario)'s getAuthPassword method.
# Usuario model
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->clave;
}

Laravel 5.3 get last insert id after registration

Using laravel5.3
php 5.6.3
I want the last inserted id in users table for the redirected page after registration
So I want the last inserted id to userprofileadd.blade.php
I have also tried ->with('id', $user->id) from register function
I don't want automatic login after registration , so I removed the login part , and after registration the user will be redirected to another form , and i want the latest user id (who ever registered) from users table
Register controller:
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\role;
use App\Userdetails;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = '/userprofileadd';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware(['auth', 'hr']);
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
'role'=>'required'
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
return User::create([
'email' => $data['email'],
'password' => bcrypt($data['password']),
'role_id'=>$data['role'],
]);
}
public function showregistrationform()
{
$roles = role::all(); // get all teams
return view('auth.register', [ 'roles' => $roles]);
}
}
register function (i have commented out login after registration)
public function register(Request $request)
{
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
// $this->guard()->login($user);
return $this->registered($request, $user)
?: redirect($this->redirectPath());
// ->with('id', $user->id)
}
if you are using model then
$user = new User();
$user->name = "JOHN";
$user->save();
$user->id; // contain the inserted id
if you are using db class
$id = DB::table('users')->insertGetId(
['email' => 'john#example.com', 'votes' => 0]
);
To get the last created user
$user = User::create([
'email' => $data['email'],
'password' => bcrypt($data['password']),
'role_id'=>$data['role'],
]);
$this->lastCreatedUserId = $user->id;
To pass the userId to custom redirection page
You may use the Laravel Auth redirectTo method. Doc.
protected function redirectTo()
{
return route('customroutename', ['id' => $this->lastCreatedUserId]);
}
Example:
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\role;
use App\Userdetails;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
class RegisterController extends Controller
{
public $lastCreatedUser;
use RegistersUsers;
protected $redirectTo = '/userprofileadd';
//The redirectTo method will take precedence over the redirectTo attribute.
protected function redirectTo()
{
//assuming your route name is 'userprofileadd' if not, use your route name of the route('/userprofileadd')
return route('userprofileadd', ['id' => $this->lastCreatedUser]);
}
public function __construct()
{
$this->middleware(['auth', 'hr']);
}
protected function validator(array $data)
{
return Validator::make($data, [
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
'role'=>'required'
]);
}
protected function create(array $data)
{
$user = User::create([
'email' => $data['email'],
'password' => bcrypt($data['password']),
'role_id'=>$data['role'],
]);
$this->lastCreatedUser = $user->id;
return $user;
}
public function showregistrationform()
{
$roles = role::all(); // get all teams
return view('auth.register', [ 'roles' => $roles]);
}
}
You can access the last created user in your UserprofileController's index method like,
public function index($id)
{
$lastCreatedUser = $id;
//you may pass this variable to the view
}
Hope it helps.. Let me know the results..
I'm not sure if this is what you're looking for or not, but you can do this to retrieve the latest record in the users table:
$latestUser = App\User::latest()->first();
Hopefully this helps.

Laravel: How can I change the default Auth Password field name?

I am currently working on my first laravel project and I am facing a problem.
If you have experience with laravel you probably know that by calling php artisan make:auth you will get a predefined mechanism that handles login and registration.
This mechanism is set to understand a couple of commonly used words in order to automate the whole procedure.
The problem that occurs in my case is that I am using oracle db and it won't let me have a table column with the name of password because its a system keyword and it throws errors when trying to insert a user.
So far, I have tried to change my password column to passwd and it worked in my registration form as expected. The User row was successfully inserted and my page was redirected to /home.
But when I try to logout and then relogin, I get this error telling me that my credentials are not correct:
As for my code, I have changed my RegisterController.php so that it takes username instead of email
protected function validator(array $data)
{
return Validator::make($data, [
'username' => 'required|max:50|unique:ECON_USERS',
'passwd' => 'required|min:6|confirmed',
]);
}
protected function create(array $data)
{
return User::create([
'username' => $data['username'],
'passwd' => bcrypt($data['passwd'])
]);
}
The User $fillable
protected $fillable = [
'username', 'passwd'
];
I am guessing that Auth is trying to authenticate with email and not username or that Auth is searching for password and not passwd.
For having username instead of email, you can overwrite username() in your LoginController.php
/**
* Get the login username to be used by the controller.
*
* #return string
*/
public function username()
{
return 'username';
}
And for passwd instead of password, you can do define an accessor in your App\User.php
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->passwd;
}
login.blade.php : Replace email input with username but do not change the name of the input for password.
Use this. It's work for me.
So far I have changed the User.php
public function getAuthPassword(){
return $this->senha;
}
and
public function setPasswordAttribute($value)
{
$this->attributes['password'] = bcrypt($value);
}
Also on LoginController.php
public function username()
{
return 'usuario';
}
In the app/Http/Controllers/Auth/LoginController override the default class by adding:
/**
* Validate the user login request.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required', 'passwd' => 'required',
]);
}
Don't forget to add use Illuminate\Http\Request;
It could be you have to add this too to your LoginController.
/**
* Get the needed authorization credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected function credentials(Request $request)
{
return $request->only($this->username(), 'passwd');
}
That should do it.
In Laravel 5.7 beside above answer you must change EloquentUserProvider class. search in the file for 'password' word in lines (107,117, and 140) you found 'password' word and change it with new name, and this is all solustion.
In User Model add this method :
public function getAuthPassword(){
return $this->new_password_name;
}
In LoginController add this :
protected function validateLogin(Request $request){
$this->validate($request, [
$this->username() => 'required',
'new_password_name' => 'required',
]);
}
protected function credentials(Request $request)
{
return $request->only($this->username(), 'new_password_name');
}
public function username()
{
return 'new_username';//or new email name if you changed
}
In login.blade.php change id and name of html element.
In EloquentUserProvider class inside validateCredentials and retrieveByCredentials function change 'password' word with the new name.
Edit :I change EloquentUserProvider class but if you think changing laravel class is a bad practice you can create custom provider and override the retrieveByCredentials and validateCredentials functions in the custom provider.
If you are using the latest version. I am returning it like the following code below for a custom password field. On my end, I am using Lumen 6.x though it would apply to current version of Laravel also.
/**
* Get the custom password field for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->custom_password_field_here;
}
IN Custom Controller
public function login(Request $request){
if (Auth::attempt(['email' => $request->email,'password' => $request->password], false)){
return redirect()->intended(route('subportal.dashboard'));
}
return $this->sendFailedLoginResponse($request);
}
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required', 'password' => 'required',
]);
}
/**
* Get the login username to be used by the controller.
*
* #return string
*/
public function username()
{
return 'email';
}
In App/Users.php
public $table = "customer";
protected $primaryKey = 'cust_id';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'pass', 'email','record_date',
];
public function getAuthPassword() {
return $this->pass;
}
In your AuthController.php (Located in app/http/Controllers/Auth)
public function postLogin(Request $request)
{
$this->validate($request, [
'username' => 'required',
'password' => 'required',
]);
$credentials = ($request->only('username', 'password'));
if ($this->auth->attempt($credentials)) {
//do something, credentials is correct!
}
return "Ops! snap! seems like you provide an invalid login credentials";
}

Laravel Auth::attempt() not actually login

When I am taking an attempt to login it just redirecting to "admin" page with any value. I did all the possible try found in google. But still not having luck. I am badly in need of help. My code is given below :
Controller: LoginController.php
<?php
class LoginController extends BaseController {
public function doLogin()
{
$rules = ['username'=>'required','password'=>'required'];
$credentials = array(
'username' => Input::get('username'),
'password' => Input::get('password')
);
$validation = Validator::make($credentials, $rules);
if($validation->fails()){
return Redirect::back()
->withInput()
->withErrors($validation);
}
else{
Auth::attempt($credentials);
return Redirect::intended('admin');
}
}
public function doLogOut()
{
Auth::logout();
return Redirect::to('/login');
}
}
Model: User.php
<?php
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
}
UserTableSeeder:
<?php
class UserTableSeeder extends Seeder {
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
$vader = DB::table('users')->insert([
'username' => 'admin',
'password' => Hash::make('admin'),
'created_at' => new DateTime(),
'updated_at' => new DateTime()
]);
}
}
Routes:
Route::post('login','LoginController#doLogIn');
Let's take a closer look at these lines:
else {
Auth::attempt($credentials);
return Redirect::intended('admin');
}
What you're doing in this snippet is
You try to log the user in.
Then you redirect, regardless of whether it worked or not.
If you want to make sure the user is actually logged in, you should wrap the attempt within an if clause.

laravel inserting into multiple tables

I have 2 tables
#something - id, name, url
#something_users - id, id_something, email, password
My models
class Something extends Eloquent
{
protected $table = 'something';
protected $fillable = ['name', 'email', 'password'];
public $errors;
public function User()
{
return $this->belongsTo('User', 'id', 'id_something');
}
}
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
protected $table = 'something_users';
protected $hidden = array('password', 'remember_token');
public function Something()
{
return $this->belongsTo('Something');
}
}
Controller
$input = Input::all();
// also some validation
$this->db->fill($input);
$this->db->password = Hash::make(Input::get('password'));
$this->db->push();
$this->db->save();
SQL
insert into `something` (`name`, `email`, `password`) values...
I need to insert name into the first table(something) and email, password into second(something_users)
How to do that? I have on clue about that.
Your relationships are a little screwed up, you probably want to change those. Note the hasMany() vs the belongsTo(). If a something can only have one user, you may wish to change the function to hasOne() from hasMany() and the name of the function to user() only because it makes more sense that way.
class Something extends Eloquent {
protected $table = 'something';
public function users()
{
return $this->hasMany('User', 'id_something');
}
}
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
protected $table = 'something_users';
protected $hidden = array('password', 'remember_token');
public function something()
{
return $this->belongsTo('Something', 'id_something');
}
}
And then to save a something and a user and have them linked, it's pretty easy.
$something = new Something;
$something->name = Input::get('name');
$something->url = Input::get('url');
$something->save();
$user = new User;
$user->email = Input::get('email');
$user->password = Hash::make(Input::get('password'));
$something->users()->save($user);
I'm not seeing your constructor so I don't know which model $this->db refers to, but you may want to replace the somethings or users depending on what you have. To keep your dependency injection going, I'd suggest naming your dependencies what they actually are.
class SomeController extends BaseController {
public function __construct(User $user, Something $something)
{
$this->user = $user;
$this->something = $something;
}
public function someFunction()
{
$this->something->name = Input::get('name');
$this->something->url = Input::get('url');
$this->something->save();
$this->user->email = Input::get('email');
$this->user->password = Hash::make(Input::get('password'));
$this->something->users()->save($this->user);
}
}
Laravel 6.
I want to add data to users table and customer table using one controller that is RegisterController.
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\Customer;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
//this part is my code
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
'role' => '2',
]);
$customer = Customer::create([
'user_id' => $user['id'],
'firstname' => $data['name'],
'lastname' => $data['name'],
'email' => $data['email'],
'address' => '',
'phone' => '',
'gender' => '',
]);
return $user;
}
}
enter image description here
enter image description here
This answer is not the best one, because this answer is just a shortcut code so that my code is not error. maybe another error will appear in the future.
but I hope my answer can solve your problem

Categories