FlyingSpoon Posted May 25, 2017 Share Posted May 25, 2017 <?php // PHP include 'mta_sdk.php'; // Correct path if you use a different one $servername = "********"; // Change these details $username = "********"; // Change these details $password = "*********"; // Change these details $dbname = "********"; // Change these details $table = "core_members"; $accountColumn = "name"; // change to "email" if you prefer logging in through email $conn = mysqli_connect($servername, $username, $password, $dbname); if (!$conn) { mta::doReturn(false, "Connection failed: " . mysqli_connect_error()); // Account not found #die("Connection failed: " . mysqli_connect_error()); } $input = mta::getInput(); if (isset($input[0]) && isset($input[1]) && isset($input[2]) && $input[0] == "verifyPasswords" ) { $sql = "SELECT `members_pass_salt`, `members_pass_hash`, `members_id` FROM `".$table."` WHERE `".$accountColumn."`='".strtolower($input[1])."' LIMIT 1"; $result = mysqli_query($conn, $sql); if (mysqli_num_rows($result) > 0) { $row = mysqli_fetch_assoc($result); if (crypt($input[2], '$2a$13$' . $row['members_pass_salt']) == $row['members_pass_hash']) { mta::doReturn(true, 0, $row, $input[3], $input[4]); // Password correct } else { mta::doReturn(false, 1, false, false, $input[4]); // Passwords don't match } } else { mta::doReturn(false, 2, false, false, $input[4]); // Account not found } } // Author: MrTasty ?> MTA SERVER SIDE SCRIPT - ABOVE IS PHP SCRIPT function UserLogin(userName,Password,Checksave) if not (userName == "") then if not (Password == "") then callRemote("[LINK]", function(response,extra,data,Checksave,player) if response == true then triggerClientEvent(player,"loginHide",getRootElement()) triggerClientEvent(player,"showNotification",player, "Successfully logged in!", "success") triggerClientEvent(player, "triggerLobby", player) UserData("success", data["member_id"], data["name"], player, userName, Password, Checksave); elseif extra == 1 then triggerClientEvent(player,"showNotification",player, "Password doesn't match!", "error") elseif extra == 2 then triggerClientEvent(player,"showNotification",player, "Account doesn't exist!", "error") end end ,"verifyPasswords", userName, Password, Checksave, source) else triggerClientEvent(source,"showNotification",source, "Please enter your password!", "error") end else triggerClientEvent(source,"showNotification",source, "Please enter your username!", "error") end end addEvent("UserWantToLogin",true) addEventHandler("UserWantToLogin",getRootElement(),UserLogin) So whenever I try to login, it says account doesnt exist, I dont understand what I'm doing wrong? Any help? @MrTasty 1 Link to comment
Addlibs Posted May 25, 2017 Share Posted May 25, 2017 (edited) Place the following file in the root of your IPS installation, where "init.php" is located. 'You should move to internally verifying the accounts. <?php include 'mta_sdk.php'; $_SERVER['SCRIPT_FILENAME'] = __FILE__; $path = ''; require_once $path . 'init.php'; \IPS\Session\Front::i(); $input = mta::getInput(); $username = $input[0]['user']; $password = $input[0]['pass']; $member = \IPS\Member::load($username, 'name'); if( !$member->member_id ) { mta::doReturn( array( 'status' => 'FAILED', 'msg' => 'ACCOUNT_NOT_FOUND', ) ); exit; } $salt = $member->members_pass_salt; $hash = crypt($password, '$2a$13$' . $salt); if (\IPS\Login::compareHashes($member->members_pass_hash, $hash) === TRUE) { mta::doReturn( array( "status" => "SUCCESS", "connect_status" => ( $member->members_bitoptions['validating'] ) ? 'VALIDATING' : 'SUCCESS', "email" => $member->email, "name" => $member->name, "connect_id" => $member->member_id, ) ); } else { mta::doReturn( array( 'status' => 'FAILED', 'msg' => 'ACCOUNT_INVALID_PASSWORD', ) ); } ?> The following is a sample Lua code based on your previous code. function UserLogin(userName,Password,Checksave) if not (userName == "") then if not (Password == "") then fetchRemote("[LINK]", function(response,errno,player) if type(response) == "table" then if response.status == "SUCCESS" then triggerClientEvent(player,"loginHide",getRootElement()) triggerClientEvent(player,"showNotification",player, "Successfully logged in!", "success") triggerClientEvent(player, "triggerLobby", player) UserData("success", data["member_id"], data["name"], player, userName, Password, Checksave) else if response.msg == "ACCOUNT_NOT_FOUND" then triggerClientEvent(player,"showNotification",player, "Account doesn't exist!", "error") elseif response.msg == "ACCOUNT_INVALID_PASSWORD" then triggerClientEvent(player,"showNotification",player, "Password doesn't match!", "error") end end elseif response == "ERROR" then triggerClientEvent(player,"showNotification",player, "Internal error. Please try again later. (Code "..errno..")", "error") end end , toJSON({user=userName, pass=Password}), false, source) else triggerClientEvent(source,"showNotification",source, "Please enter your password!", "error") end else triggerClientEvent(source,"showNotification",source, "Please enter your username!", "error") end end addEvent("UserWantToLogin",true) addEventHandler("UserWantToLogin",getRootElement(),UserLogin) None of this is tested but I skimmed through this and I think it should work. Edited May 25, 2017 by MrTasty Link to comment
FlyingSpoon Posted May 25, 2017 Author Share Posted May 25, 2017 (edited) function UserLogin(userName,Password,Checksave) if not (userName == "") then if not (Password == "") then fetchRemote("http://forums.link.com/login.php", function(response,errno,player) if type(response) == "table" then if response.status == "SUCCESS" then triggerClientEvent(player,"loginHide",getRootElement()) triggerClientEvent(player,"showNotification",player, "Successfully logged in!", "success") UserData("success", data["member_id"], data["name"], player, userName, Password, Checksave) outputDebugString("True") else if response.msg == "ACCOUNT_NOT_FOUND" then triggerClientEvent(player,"showNotification",player, "Account doesn't exist!", "error") outputDebugString("False") elseif response.msg == "ACCOUNT_INVALID_PASSWORD" then triggerClientEvent(player,"showNotification",player, "Password doesn't match!", "error") end end elseif response == "ERROR" then triggerClientEvent(player,"showNotification",player, "Internal error. Please try again later. (Code "..errno..")", "error") end end , toJSON({user=userName, pass=Password}), false, source) else triggerClientEvent(source,"showNotification",source, "Please enter your password!", "error") end else triggerClientEvent(source,"showNotification",source, "Please enter your username!", "error") end end addEvent("UserWantToLogin",true) addEventHandler("UserWantToLogin",getRootElement(),UserLogin) function UserData(Status,UserID,uName,player,userName,Password,Checksave) if Status == "success" then if not getAccount (UserID) then acc = addAccount(tostring(UserID),tostring(Password)) end if not getAccount(UserID,Password) then setAccountPassword(getAccount(UserID),Password) end local acc = getAccount ( UserID,Password) if(not isGuestAccount(acc)) then logOut(player); end logIn (player, acc, Password) setElementData(player,"getForumID",UserID) setElementData(player,"getForumName",uName) end end LUA Script ^ <?php include 'mta_sdk.php'; $_SERVER['SCRIPT_FILENAME'] = __FILE__; $path = ''; require_once $path . 'init.php'; \IPS\Session\Front::i(); $input = mta::getInput(); $username = $input[0]['user']; $password = $input[0]['pass']; $member = \IPS\Member::load($username, 'name'); if( !$member->member_id ) { mta::doReturn( array( 'status' => 'FAILED', 'msg' => 'ACCOUNT_NOT_FOUND', ) ); exit; } $salt = $member->members_pass_salt; $hash = crypt($password, '$2a$13$' . $salt); if (\IPS\Login::compareHashes($member->members_pass_hash, $hash) === TRUE) { mta::doReturn( array( "status" => "SUCCESS", "connect_status" => ( $member->members_bitoptions['validating'] ) ? 'VALIDATING' : 'SUCCESS', "email" => $member->email, "name" => $member->name, "connect_id" => $member->member_id, ) ); } else { mta::doReturn( array( 'status' => 'FAILED', 'msg' => 'ACCOUNT_INVALID_PASSWORD', ) ); } ?> PHP ^ --- There's no output in the debug, and nothing happens, any ideas? @MrTasty Edited May 25, 2017 by raysmta Link to comment
Addlibs Posted May 26, 2017 Share Posted May 26, 2017 (edited) function UserLogin(userName,Password,Checksave) if not (userName == "") then if not (Password == "") then fetchRemote("http://forums.link.com/login.php", function(response,errno,player) local response = fromJSON(response) if type(response) == "table" then if response.status == "SUCCESS" then triggerClientEvent(player,"loginHide",getRootElement()) triggerClientEvent(player,"showNotification",player, "Successfully logged in!", "success") UserData("success", data["member_id"], data["name"], player, userName, Password, Checksave) else if response.msg == "ACCOUNT_NOT_FOUND" then triggerClientEvent(player,"showNotification",player, "Account doesn't exist!", "error") elseif response.msg == "ACCOUNT_INVALID_PASSWORD" then triggerClientEvent(player,"showNotification",player, "Password doesn't match!", "error") else outputDebugString("UNRECOGNISED RESPONSE @ "..getPlayerName(player)"'s login attempt.") end end elseif response == "ERROR" then triggerClientEvent(player,"showNotification",player, "Internal error. Please try again later. (Code "..errno..")", "error") outputDebugString("INTERNAL ERROR "..errno.." @ "..getPlayerName(player)"'s login attempt.") else outputDebugString("PARSING ERROR @ "..getPlayerName(player)"'s login attempt.") -- maybe the response was sent in a way other than a table, but its not an error either end end , toJSON({user=userName, pass=Password}), false, source) else triggerClientEvent(source,"showNotification",source, "Please enter your password!", "error") end else triggerClientEvent(source,"showNotification",source, "Please enter your username!", "error") end end addEvent("UserWantToLogin",true) addEventHandler("UserWantToLogin",getRootElement(),UserLogin) function UserData(Status,UserID,uName,player,userName,Password,Checksave) if Status == "success" then if not getAccount (UserID) then acc = addAccount(tostring(UserID),tostring(Password)) end if not getAccount(UserID,Password) then setAccountPassword(getAccount(UserID),Password) end local acc = getAccount ( UserID,Password) if(not isGuestAccount(acc)) then logOut(player); end logIn (player, acc, Password) setElementData(player,"getForumID",UserID) setElementData(player,"getForumName",uName) end end Edited May 26, 2017 by MrTasty 1 Link to comment
Addlibs Posted May 26, 2017 Share Posted May 26, 2017 (edited) The code above should work. The problem was I didn't convert the JSON back to Lua (the SDK sends arrays as JSON). (too much time passed for me to edit and append this message to the post above -.-) Also, you may wish to check response.connect_status when deciding whether to grant permission to log in. This value will be either "SUCCESS" or "VALIDATING", so you may block logins from accounts which haven't confirmed their email yet. Edited May 26, 2017 by MrTasty 2 Link to comment
FlyingSpoon Posted May 26, 2017 Author Share Posted May 26, 2017 Thank you! Works like charm! Link to comment
Ruzy Posted July 23, 2017 Share Posted July 23, 2017 (edited) When i add this code it outputs: outputDebugString("PARSING ERROR @ "..getPlayerName(player)"'s login attempt.") Any idea how to fix this? function CPlayer:OnPlayerRequestLogin(data) if not (data[1] == "") then if not (data[2] == "") then fetchRemote("http://forums.link.com/login.php", function(response,errno,player) local response = fromJSON(response) if type(response) == "table" then if response.status == "SUCCESS" then DB:Query(function(res) if #res > 0 then -- login normal Core:Notificate(player, "You successfully logged in. Welcome back" ..data[1].."!", "success") self:InitiateLogin(0x118100F1) elseif #res == 0 then -- login new player self.accountName = data[1] self.uid = response.connect_id local date = getRealTime() --id,name,pw,alias,date,lastseen,playtime,countrycode,lang,team,teamlvl,permlvl,warns,sanction.mutetime DB:Exec("INSERT INTO `Accounts` VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", self.uid, data[1], hash("sha256", data[2]), self.name, ("%s-%s-%s"):format(date.year+1900, date.month+1, date.monthday),("%s-%s-%s %s:%s:%s"):format(date.year+1900, date.month+1, date.monthday, date.hour, date.minute, date.second), 0, self:GetCountry(), "", 0, 1, 0, 0, 0) --id,money,exp,mapsdm,mapsdd,mapshunter,pointsdm,pointsdd,pointshunter DB:Exec("INSERT INTO `Players` VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", self.uid, 0, 0, 0, 0, 0, 0, 0, 0) --id,chat,chat,chat,chat,carhide,carfade,drawhud,mapmusic DB:Exec("INSERT INTO `Settings` VALUES (?,1,1,1,1,0,1,1,1)", self.uid) --id,moneyspend,mapsbought,mapswon,pvpwon,spinwon,eventswon,timesjoined,dmdeaths,dmmaps,dmfinished,dmwins,dmtoptimes,ddkils,dddeaths,ddmaps,ddwins,ddwinstreak,hunterkills,hunterdeaths,hunterrockets,huntermaps,hunterwins,hunterwinstreak DB:Exec("INSERT INTO `PlayerStats` VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", self.uid, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) self:InitiateLogin(0x118100F1) Core:Notificate(player, "You successfully logged in. Welcome, "..data[1].." to vigour gaming!", "success") end end, "SELECT `ID` from `Accounts` WHERE `Accountname` = ?", data[1]) else if response.msg == "ACCOUNT_NOT_FOUND" then Core:Notificate(player, "Account not found!", "error") Core:Notificate(player, "Register yourself if you don't have an account", "info") triggerClientEvent(player, "URAL:Response", player, 404) elseif response.msg == "ACCOUNT_INVALID_PASSWORD" then Core:Notificate(player, "Wrong account password!", "error") triggerClientEvent(player, "URAL:Response", player, 401) else outputDebugString("UNRECOGNISED RESPONSE @ "..getPlayerName(player)"'s login attempt.") end end elseif response == "ERROR" then Core:Notificate(player, "Internal error. Please try again later. (Code "..errno..")", "error") outputDebugString("INTERNAL ERROR "..errno.." @ "..getPlayerName(player)"'s login attempt.") else outputDebugString("PARSING ERROR @ "..getPlayerName(player)"'s login attempt.") -- maybe the response was sent in a way other than a table, but its not an error either end end, toJSON({user=data[1], pass=data[2]}), false, source) else Core:Notificate(self.obj, "Enter your password!", "error") triggerClientEvent(self.obj, "URAL:Response", self.obj, 401) end else Core:Notificate(self.obj, "Enter your username!", "error") triggerClientEvent(self.obj, "URAL:Response", self.obj, 401) end end Edited July 23, 2017 by Ruzy Link to comment
Addlibs Posted July 23, 2017 Share Posted July 23, 2017 (edited) Change lines 4-5 and line 42 to function(response_,errno,player) -- line 4 local response = fromJSON(response_) -- line 5 -- ... elseif response_ == "ERROR" then --line 42 -- ... end This should result in the code correctly informing you of the HTTP error code, and thus no valid response was given (i.e. 500 error) If it still comes up as a parsing error, that means the website's response is incorrectly formatted. Edited July 23, 2017 by MrTasty Link to comment
Ruzy Posted July 23, 2017 Share Posted July 23, 2017 It's still comes up as parsing error. mta_sdk.php is installed too and this is the login.php code: <?php include 'mta_sdk.php'; $_SERVER['SCRIPT_FILENAME'] = __FILE__; $path = ''; require_once $path . 'init.php'; \IPS\Session\Front::i(); $input = mta::getInput(); $username = $input[0]['user']; $password = $input[0]['pass']; $member = \IPS\Member::load($username, 'name'); if( !$member->member_id ) { mta::doReturn( array( 'status' => 'FAILED', 'msg' => 'ACCOUNT_NOT_FOUND', ) ); exit; } $salt = $member->members_pass_salt; $hash = crypt($password, '$2a$13$' . $salt); if (\IPS\Login::compareHashes($member->members_pass_hash, $hash) === TRUE) { mta::doReturn( array( "status" => "SUCCESS", "connect_status" => ( $member->members_bitoptions['validating'] ) ? 'VALIDATING' : 'SUCCESS', "email" => $member->email, "name" => $member->name, "connect_id" => $member->member_id, ) ); } else { mta::doReturn( array( 'status' => 'FAILED', 'msg' => 'ACCOUNT_INVALID_PASSWORD', ) ); } ?> Link to comment
Addlibs Posted July 23, 2017 Share Posted July 23, 2017 (edited) fetchRemote("http://forums.link.com/login.php", -- of course use your own URL here function(response_,errno,player) outputDebugString(tostring(response_)) end , toJSON({user="any username", pass="and any password"}), false) Try running this, preferably with runcode through the HTTP interface (usually at http://<your server ip>:22003/runcode/ unless you changed the HTTP port) and check for the response - it should be a JSON string. Edited July 23, 2017 by MrTasty Link to comment
FlyingSpoon Posted July 23, 2017 Author Share Posted July 23, 2017 Would it be a problem, if the Forum was running on a Windows based server? Link to comment
Ruzy Posted July 23, 2017 Share Posted July 23, 2017 (edited) [2017-07-23 06:36:21] INFO: <br /> <b>Deprecated</b>: Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a future version. To avoid this warning set 'always_populate_raw_post_data' to '-1' in php.ini and use the php://input stream instead. in <b>Unknown</b> on line <b>0</b><br /> <br /> <b>Warning</b>: Cannot modify header information - headers already sent in <b>Unknown</b> on line <b>0</b><br /> [{"status":"SUCCESS","connect_status":"SUCCESS","email":"****@gmail.com","name":"Ruzy","connect_id":1}] Edited July 23, 2017 by Ruzy Link to comment
Addlibs Posted July 23, 2017 Share Posted July 23, 2017 (edited) Aha. Parsing error - the response from the site, although it contains the JSON code, it is not the JSON code on its own. You should do something about those error messages so that the only response from the server is, is the JSON string (what you see on line 5) The first error can be corrected by changing php.ini as instructed, the other error is a result of the first error being written up before the forum code was initialised (which includes setting headers, I guess) and that causes an error - setting headers when something was already outputted (the previous error). Edited July 23, 2017 by MrTasty 1 Link to comment
Ruzy Posted July 23, 2017 Share Posted July 23, 2017 (edited) It worked, thank you! Edited July 23, 2017 by Ruzy Link to comment
FlyingSpoon Posted February 21, 2018 Author Share Posted February 21, 2018 (edited) BUMP It is unable to get the datas, e.g. data["member_id"], data["name"], it worked when I used callRemote, but fails to work now since it is not getting the data through the arguments, any ideas how I can fix this? function UserLogin(userName,Password,Checksave) if not (userName == "") then if not (Password == "") then fetchRemote("http://forums.link.com/login.php", function(response,errno,player) local response = fromJSON(response) if type(response) == "table" then if response.status == "SUCCESS" then triggerClientEvent(player,"loginHide",getRootElement()) triggerClientEvent(player,"showNotification",player, "Successfully logged in!", "success") UserData("success", data["member_id"], data["name"], player, userName, Password, Checksave) else if response.msg == "ACCOUNT_NOT_FOUND" then triggerClientEvent(player,"showNotification",player, "Account doesn't exist!", "error") elseif response.msg == "ACCOUNT_INVALID_PASSWORD" then triggerClientEvent(player,"showNotification",player, "Password doesn't match!", "error") else outputDebugString("UNRECOGNISED RESPONSE @ "..getPlayerName(player)"'s login attempt.") end end elseif response == "ERROR" then triggerClientEvent(player,"showNotification",player, "Internal error. Please try again later. (Code "..errno..")", "error") outputDebugString("INTERNAL ERROR "..errno.." @ "..getPlayerName(player)"'s login attempt.") else outputDebugString("PARSING ERROR @ "..getPlayerName(player)"'s login attempt.") -- maybe the response was sent in a way other than a table, but its not an error either end end , toJSON({user=userName, pass=Password}), false, source) else triggerClientEvent(source,"showNotification",source, "Please enter your password!", "error") end else triggerClientEvent(source,"showNotification",source, "Please enter your username!", "error") end end addEvent("UserWantToLogin",true) addEventHandler("UserWantToLogin",getRootElement(),UserLogin) function UserData(Status,UserID,uName,player,userName,Password,Checksave) if Status == "success" then if not getAccount (UserID) then acc = addAccount(tostring(UserID),tostring(Password)) end if not getAccount(UserID,Password) then setAccountPassword(getAccount(UserID),Password) end local acc = getAccount ( UserID,Password) if(not isGuestAccount(acc)) then logOut(player); end logIn (player, acc, Password) setElementData(player,"getForumID",UserID) setElementData(player,"getForumName",uName) end end Edited February 21, 2018 by ℓιgнт Link to comment
NeXuS™ Posted February 21, 2018 Share Posted February 21, 2018 Where is the "data" table tho? Link to comment
FlyingSpoon Posted February 21, 2018 Author Share Posted February 21, 2018 If you scroll to my first post I made, I used data within the function of callRemote as an argument. I don't know if the same scenario applies to fetchRemote, I've tried it but sadly it doesn't work. Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now