feat(authentication): integrasi sistem otentikasi dengan User Identity Management (UIM)
### Perubahan Utama - Tambah integrasi dengan sistem UIM untuk otentikasi pengguna. - Update logika otentikasi berdasarkan metode yang ditentukan (`METHOD_AUTH`). - Penanganan otomatis terhadap pengguna baru dengan pembuatan akun dan penentuan role. ### Detail Perubahan 1. **Integrasi Sistem UIM**: - Tambah metode `userIdManagemeent` untuk menangani otentikasi pengguna melalui UIM. - Implementasikan fungsi `verify_user` di helper baru (`uim.php`) untuk berkomunikasi dengan server UIM. - Tambahkan class baru `Uim` untuk menangani verifikasi pengguna melalui koneksi TCP. - Dekode respons dari UIM untuk memproses data pengguna. 2. **Penyesuaian Logika Otentikasi**: - Jika `METHOD_AUTH` diset ke `uim`, sistem akan dialihkan ke otentikasi melalui UIM. - Tambahkan logika fallback untuk otentikasi standar menggunakan Laravel jika UIM tidak digunakan. 3. **Pembuatan Pengguna Baru**: - Buat pengguna dalam database secara otomatis jika belum terdaftar menggunakan informasi dari UIM. - Validasi kode cabang berdasarkan data UIM untuk menentukan cabang yang relevan. - Penetapan role pengguna sesuai dengan kode grup yang diterima dari UIM. 4. **Manajemen Cabang**: - Cari cabang terkait berdasarkan 4 digit terakhir kode cabang (`KD_CABANG`) dari data UIM. - Simpan ID cabang di session untuk pengguna yang berhasil otentikasi. 5. **Penanganan Validasi dan Error**: - Tambahkan mekanisme penanganan rate limit jika otentikasi gagal. - Beri pesan error yang lebih informatif saat otentikasi gagal melalui UIM. 6. **Update Konfigurasi Module**: - Tambahkan path baru untuk helper `uim.php` di `module.json`.
This commit is contained in:
154
app/Classes/Uim.php
Normal file
154
app/Classes/Uim.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Authentication\Classes;
|
||||
|
||||
class Uim
|
||||
{
|
||||
private string $serviceHost;
|
||||
private int $servicePort;
|
||||
private string $appId;
|
||||
private string $serverAddress;
|
||||
|
||||
/**
|
||||
* @param string $serviceHost The host address of the user verification service
|
||||
* @param int $servicePort The port of the user verification service
|
||||
* @param string $appId The application ID
|
||||
* @param string $serverAddress The server address
|
||||
*/
|
||||
public function __construct(string $serviceHost, int $servicePort, string $appId, string $serverAddress)
|
||||
{
|
||||
$this->serviceHost = $serviceHost;
|
||||
$this->servicePort = $servicePort;
|
||||
$this->appId = $appId;
|
||||
$this->serverAddress = $serverAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a user's credentials
|
||||
*
|
||||
* @param string $userId The user ID
|
||||
* @param string $password The user password
|
||||
*
|
||||
* @return string The verification response
|
||||
* @throws Exception If connection fails or other errors occur
|
||||
*/
|
||||
public function verify(string $userId, string $password)
|
||||
: string
|
||||
{
|
||||
$socket = $this->openSecureConnection();
|
||||
|
||||
$postData = $this->buildPostData($userId, $password);
|
||||
$this->sendHttpRequest($socket, $postData);
|
||||
|
||||
$response = $this->readResponse($socket);
|
||||
fclose($socket);
|
||||
|
||||
return $this->decodeHexResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a secure connection to the verification service
|
||||
*
|
||||
* @return resource The socket connection
|
||||
* @throws Exception If connection fails
|
||||
*/
|
||||
private function openSecureConnection()
|
||||
{
|
||||
$errno = 0;
|
||||
$errstr = '';
|
||||
$socket = @fsockopen("tcp://" . $this->serviceHost, $this->servicePort, $errno, $errstr, 30);
|
||||
|
||||
if (!$socket) {
|
||||
throw new Exception("Connection failed: $errstr ($errno)");
|
||||
}
|
||||
|
||||
return $socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the form data for the verification request
|
||||
*
|
||||
* @param string $userId The user ID
|
||||
* @param string $password The user password
|
||||
*
|
||||
* @return string The URL-encoded form data
|
||||
*/
|
||||
private function buildPostData(string $userId, string $password)
|
||||
: string
|
||||
{
|
||||
return http_build_query([
|
||||
'appsid' => $this->appId,
|
||||
'loginid' => $userId,
|
||||
'passwd' => $password,
|
||||
'addr' => $this->serverAddress,
|
||||
'version' => 2
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the HTTP request to the verification service
|
||||
*
|
||||
* @param resource $socket The socket connection
|
||||
* @param string $postData The data to send
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function sendHttpRequest($socket, string $postData)
|
||||
: void
|
||||
{
|
||||
fwrite($socket, "POST /user_verification_dev.php HTTP/1.0\r\n");
|
||||
fwrite($socket, "Host: {$this->serviceHost}\r\n");
|
||||
fwrite($socket, "Content-type: application/x-www-form-urlencoded\r\n");
|
||||
fwrite($socket, "Content-length: " . strlen($postData) . "\r\n");
|
||||
fwrite($socket, "Accept: */*\r\n");
|
||||
fwrite($socket, "\r\n");
|
||||
fwrite($socket, "$postData\r\n");
|
||||
fwrite($socket, "\r\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the response from the verification service
|
||||
*
|
||||
* @param resource $socket The socket connection
|
||||
*
|
||||
* @return string The response body
|
||||
*/
|
||||
private function readResponse($socket)
|
||||
: string
|
||||
{
|
||||
// Skip headers
|
||||
$headers = "";
|
||||
while ($str = trim(fgets($socket, 4096))) {
|
||||
$headers .= "$str\n";
|
||||
}
|
||||
|
||||
// Read body
|
||||
$body = "";
|
||||
while (!feof($socket)) {
|
||||
$body .= fgets($socket, 4096);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a hex-encoded response
|
||||
*
|
||||
* @param string $data The hex-encoded data
|
||||
*
|
||||
* @return string The decoded string
|
||||
*/
|
||||
private function decodeHexResponse(string $data)
|
||||
: string
|
||||
{
|
||||
$text = '';
|
||||
$total = strlen($data);
|
||||
|
||||
for ($j = 0; $j < $total; $j += 2) {
|
||||
$text .= chr(hexdec(substr($data, $j, 2)));
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
|
||||
17
app/Helpers/uim.php
Normal file
17
app/Helpers/uim.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
use Modules\Authentication\Classes\Uim;
|
||||
|
||||
if (!function_exists('verify_user')) {
|
||||
function verify_user($id, $passwd, $SERVER_ADDR, $IPUserManager, $portUserManager, $appId)
|
||||
{
|
||||
try {
|
||||
$verifier = new Uim($IPUserManager, $portUserManager, $appId, $SERVER_ADDR);
|
||||
return $verifier->verify($id, $passwd);
|
||||
} catch (Exception $e) {
|
||||
// Handle error more gracefully than the original die()
|
||||
error_log("User verification error: " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,13 @@
|
||||
|
||||
use Illuminate\Auth\Events\Lockout;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Modules\Basicdata\Models\Branch;
|
||||
use Modules\Usermanagement\Models\User;
|
||||
|
||||
class LoginRequest extends FormRequest
|
||||
{
|
||||
@@ -32,28 +35,100 @@
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function authenticate()
|
||||
: void
|
||||
public function authenticate(): void
|
||||
{
|
||||
$this->ensureIsNotRateLimited();
|
||||
|
||||
$credentials = $this->only('login', 'password');
|
||||
$loginField = filter_var($credentials['login'], FILTER_VALIDATE_EMAIL) ? 'email' : 'nik';
|
||||
|
||||
$authData = [
|
||||
$loginField => $credentials['login'],
|
||||
'password' => $credentials['password'],
|
||||
];
|
||||
|
||||
if (!Auth::attempt($authData, $this->boolean('remember'))) {
|
||||
RateLimiter::hit($this->throttleKey());
|
||||
if ($_ENV['METHOD_AUTH'] == 'uim') {
|
||||
$this->userIdManagemeent($credentials);
|
||||
} else {
|
||||
if (!Auth::attempt($authData, $this->boolean('remember'))) {
|
||||
RateLimiter::hit($this->throttleKey());
|
||||
throw ValidationException::withMessages([
|
||||
'login' => trans('auth.failed'),
|
||||
]);
|
||||
}
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'login' => trans('auth.failed'),
|
||||
]);
|
||||
RateLimiter::clear($this->throttleKey());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate user through user manager
|
||||
*
|
||||
* @param array $credentials
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
protected function userIdManagemeent($credentials)
|
||||
{
|
||||
$userArray = [];
|
||||
$id = $credentials['login'];
|
||||
$passwd = $credentials['password'];
|
||||
$SERVER_ADDR = request()->ip();
|
||||
$IPUserManager = $_ENV['IP_USER_MANAGER'];
|
||||
$portUserManager = $_ENV['PORT_USER_MANAGER'];
|
||||
$appId = $_ENV['APP_ID'];
|
||||
|
||||
$userData = verify_user($id, $passwd, $SERVER_ADDR, $IPUserManager, $portUserManager, $appId);
|
||||
|
||||
if (strlen($userData) > 1) {
|
||||
$userRawArray = explode("\t", $userData);
|
||||
|
||||
foreach ($userRawArray as $rval) {
|
||||
[$key, $val] = explode('=', $rval);
|
||||
$userArray[0][$key] = $val;
|
||||
}
|
||||
|
||||
session()->put($userArray[0]);
|
||||
|
||||
// Use the login value to find the user
|
||||
$loginField = filter_var($credentials['login'], FILTER_VALIDATE_EMAIL) ? 'email' : 'nik';
|
||||
$user = User::where($loginField, $credentials['login'])->first();
|
||||
|
||||
$someValue = $userArray[0]['KD_CABANG']; // Example value containing the code
|
||||
$lastFourDigits = substr($someValue, -4); // Gets the last 4 characters
|
||||
$branch = Branch::where('code', 'LIKE', '%' . $lastFourDigits)->first();
|
||||
|
||||
session()->put('branch_id',$branch->id);
|
||||
|
||||
if (!$user) {
|
||||
//get branch id by 4 digit terakhir 0029
|
||||
|
||||
$user = User::create([
|
||||
'name' => $userArray[0]['NAMA_USER'],
|
||||
'email' => $loginField === 'email' ? $credentials['login'] : null,
|
||||
'nik' => $loginField === 'nik' ? $credentials['login'] : null,
|
||||
'password' => bcrypt($credentials['password']),
|
||||
'branch_id' => $branch ? $branch->id : null,
|
||||
]);
|
||||
|
||||
switch ($userArray[0]['KD_GROUP']) {
|
||||
case '001':
|
||||
$user->assignRole('administrator');
|
||||
break;
|
||||
case '025':
|
||||
$user->assignRole('customer_service');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Auth::loginUsingId($user->id, true);
|
||||
$this->session()->regenerate();
|
||||
|
||||
RateLimiter::clear($this->throttleKey());
|
||||
}
|
||||
|
||||
RateLimiter::clear($this->throttleKey());
|
||||
// Authentication failed
|
||||
RateLimiter::hit($this->throttleKey());
|
||||
throw ValidationException::withMessages([
|
||||
'login' => trans('auth.failed'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
"providers": [
|
||||
"Modules\\Authentication\\Providers\\AuthenticationServiceProvider"
|
||||
],
|
||||
"files": [],
|
||||
"files": [
|
||||
"app/Helpers/uim.php"
|
||||
],
|
||||
"menu": {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user