This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
ratchetgame98's profile picture

Username and Password Server

Started by ratchetgame98, 17 July 2013 - 09:35 AM
ratchetgame98 #1
Posted 17 July 2013 - 11:35 AM
In my server, I have a computer room with a lot of computers, but I would really like a username and password server for the clients. Can someone please help. I will appreciate it
Zudo #2
Posted 17 July 2013 - 11:44 AM
Check out the wiki.
Bubba #3
Posted 17 July 2013 - 03:15 PM
First you'll want to set up a server that is sitting in a while loop listening for usernames/passwords. For example:

local auth_channel = 234 --#This is just a random channel that we'll use for listening on
local modem = peripheral.wrap("top") --#Or whatever the side is
modem.open(auth_channel)

while true do
  local event, sender, reply, message = os.pullEvent("modem_message")
end

Next you'll want to flesh out that while loop with some way to verify actual requests. You'll need a way to store usernames/passwords as well - I would suggest using tables like this:

local users = {
  ["username"] = "password";
  ["bubba"] = "not_my_password";
}

Then make a function that verifies the user:

local function onRequest(message)
  --[[#A user has to send their messages in string form. In order to check both 
      #the username and password from a single message however, it would be benficial to use a table.
      #Fortunately, textutils provides the perfect utility for this.]]
  local tMessage = textutils.unserialize(message)
  if not tMessage then --#The user sent a message in the wrong form
    print("Invalid message type received - not a table!")
  elseif users[tMessage["username"]]==tMessage["password"] then --#If they sent a correct user/password
    return true
  else --#Invalid username or password
    return false
  end
end

So now we have a users table and a way to verify messages. All that's left now is to insert the onRequest function into our previous while loop.


local auth_channel = 234 --#This is just a random channel that we'll use for listening on
local modem = peripheral.wrap("top") --#Or whatever the side is
modem.open(auth_channel)

while true do
  local event, modem_side, sender, reply_channel, message = os.pullEvent("modem_message")
  if onRequest(message) then --#If they sent a valid message
    modem.transmit(reply_channel, auth_channel, "valid")
  else --#They sent a bad username/password or maybe not even in a table format
    modem.transmit(reply_channel, auth_channel, "invalid")
  end
end

Done with the server code, now onto the client code. This is quite simple. We'll want a way for users to input a username/password, and then we'll need to save that into a table. We can then use textutils.serialize to format that table into a string and send it along to the server.


local auth_channel = 234 --#Ensure that the auth channel is the same!
local myChannel = 10 --#Any channel the user wishes
local modem = peripheral.wrap("top")
modem.open(myChannel) --#We don't need to open the auth_channel to send messages, only if we need to receive on that channel

local authenticated = false --#In order to break the loop, we can simply change this to true.
while not authenticated do
  term.clear() term.setCursorPos(1,1)
  term.write("Username: ")
  local username = read() --#Gets the user's input
  local password = read("*") --#The asterisk is the masking character

  local user_table = {["username"] = username, ["password"] = password}
  modem.transmit(auth_channel, myChannel, textutils.serialize(user_table)) --#Go ahead and send off the info to the server
  local response = false
  while not response do --Now we wait for a response
    local event, modem_side, sender_channel, reply_channel, message = os.pullEvent("modem_message")
    if reply_channel == auth_channel then --#If it is indeed the server that sent the message
      response = true
      if message == "valid" then --#It was indeed a valid username/password combo
        print("Valid username/password!") --#Do whatever you want here
        authenticated = true
        break
      else --#Nope, invalid.
        print("Invalid username/password!")
      end
    end
  end
end

And that's about it! Hopefully that's not too much to take in. If you need any help, feel free to ask.
albrat #4
Posted 17 July 2013 - 03:43 PM
Done with the server code, now onto the client code. This is quite simple. We'll want a way for users to input a username/password, and then we'll need to save that into a table. We can then use textutils.serialize to format that table into a string and send it along to the server.


local auth_channel = 234 --#Ensure that the auth channel is the same!
local myChannel = 10 --#Any channel the user wishes
local modem = peripheral.wrap("top")
modem.open(myChannel) --#We don't need to open the auth_channel to send messages, only if we need to receive on that channel

while true do
  term.clear() term.setCursorPos(1,1)
  term.write("Username: ")
  local username = read() --#Gets the user's input
  local password = read("*") --#The asterisk is the masking character

  local user_table = {["username"] = username, ["password"] = password}
  modem.transmit(auth_channel, myChannel, textutils.serialize(user_table)) --#Go ahead and send off the info to the server
  while true do --Now we wait for a response
	local event, modem_side, sender_channel, reply_channel, message = os.pullEvent("modem_message")
	if reply_channel == auth_channel then --#If it is indeed the server that sent the message
	  if message == "valid" then --#It was indeed a valid username/password combo
		print("Valid username/password!") --#Do whatever you want here
	  else --#Nope, invalid.
		print("Invalid username/password!")
	  end
	end
  end
end

And that's about it! Hopefully that's not too much to take in. If you need any help, feel free to ask.

you forgot to break the while true loop. it will start again and ask for a username and password… even if correct. Just to catch it before it comes back to haunt :D/>



local oldpullevent = os.pullevent
local os.pullevent = os.pullEventRaw
local auth_channel = 234 --#Ensure that the auth channel is the same!
local myChannel = 10 --#Any channel the user wishes
local modem = peripheral.wrap("top")
modem.open(myChannel) --#We don't need to open the auth_channel to send messages, only if we need to receive on that channel

while true do
  term.clear() term.setCursorPos(1,1)
  term.write("Username: ")
  local username = read() --#Gets the user's input
  local password = read("*") --#The asterisk is the masking character

  local user_table = {["username"] = username, ["password"] = password}
  modem.transmit(auth_channel, myChannel, textutils.serialize(user_table)) --#Go ahead and send off the info to the server
  while true do --Now we wait for a response
	local event, modem_side, sender_channel, reply_channel, message = os.pullEvent("modem_message")
	if reply_channel == auth_channel then --#If it is indeed the server that sent the message
	  if message == "valid" then --#It was indeed a valid username/password combo
		printError("Valid username/password!") --#Do whatever you want here + sets the exit error.
	    os.pullEvent = oldpullevent
	    error() -- Exit the program

	  else --#Nope, invalid.
		print("Invalid username/password!")
	    sleep(3)
	  end
	end
  end
end
Bubba #5
Posted 17 July 2013 - 04:09 PM
-snip-

Thanks for catching that. :)/>

However, I don't think erroring is a good way to get out of the program. Using a break statement is much better and allows you to use the same program to do other tasks after authentication. I have updated my original post to reflect this.
zero_cool #6
Posted 17 July 2013 - 04:30 PM
I'm planning to do something similar and have a few questions.

1. Is this modem thing for wired or wireless modems or does it work with both the same way? (yeah, a nooby question, i know :D/>)
2. Is there a hash function built in CC? That way I would not have to transmit the password directly. Of course one could then simply login with the hash which would have the same effect, but if the hash contains something like the current time (1-minute-accurate) this would generate a token which is only valid for 1 minute at most. Or is there even a way to use assymetric encryption (or should I go ahead and implement RSA myself? :D/>)?
3. If the password validation process, or any other process handled by the server, would take some time, this would block the connection for that time… Is there a way to spawn like a new thread for every request that reaches the server? I know there are the parallel and the coroutine API, but the wiki describes them in a not very detailed way.

Thx
albrat #7
Posted 17 July 2013 - 05:26 PM
I do actually have a server setup for my passwords, that also displays the time, as an example of how fast the server can respond… I have it listening for rednet messages on a 0.8 pause, then update time. * this means if I get a rednet message it does not update time untill that message is dealt with and responded too…

So far, I have yet to see a login effect the update speed of the time / seconds passing (aka minecraft minutes)

I have to update my server code… found a bug in it. along the lines of a correct password would log you in as any user. after i fix this tomorrow I will try and do a pastebin upload.
ratchetgame98 #8
Posted 21 July 2013 - 06:33 AM
First you'll want to set up a server that is sitting in a while loop listening for usernames/passwords. For example:

local auth_channel = 234 --#This is just a random channel that we'll use for listening on
local modem = peripheral.wrap("top") --#Or whatever the side is
modem.open(auth_channel)

while true do
  local event, sender, reply, message = os.pullEvent("modem_message")
end

Next you'll want to flesh out that while loop with some way to verify actual requests. You'll need a way to store usernames/passwords as well - I would suggest using tables like this:

local users = {
  ["username"] = "password";
  ["bubba"] = "not_my_password";
}

Then make a function that verifies the user:

local function onRequest(message)
  --[[#A user has to send their messages in string form. In order to check both
	  #the username and password from a single message however, it would be benficial to use a table.
	  #Fortunately, textutils provides the perfect utility for this.]]
  local tMessage = textutils.unserialize(message)
  if not tMessage then --#The user sent a message in the wrong form
	print("Invalid message type received - not a table!")
  elseif users[tMessage["username"]]==tMessage["password"] then --#If they sent a correct user/password
	return true
  else --#Invalid username or password
	return false
  end
end

So now we have a users table and a way to verify messages. All that's left now is to insert the onRequest function into our previous while loop.


local auth_channel = 234 --#This is just a random channel that we'll use for listening on
local modem = peripheral.wrap("top") --#Or whatever the side is
modem.open(auth_channel)

while true do
  local event, modem_side, sender, reply_channel, message = os.pullEvent("modem_message")
  if onRequest(message) then --#If they sent a valid message
	modem.transmit(reply_channel, auth_channel, "valid")
  else --#They sent a bad username/password or maybe not even in a table format
	modem.transmit(reply_channel, auth_channel, "invalid")
  end
end

Done with the server code, now onto the client code. This is quite simple. We'll want a way for users to input a username/password, and then we'll need to save that into a table. We can then use textutils.serialize to format that table into a string and send it along to the server.


local auth_channel = 234 --#Ensure that the auth channel is the same!
local myChannel = 10 --#Any channel the user wishes
local modem = peripheral.wrap("top")
modem.open(myChannel) --#We don't need to open the auth_channel to send messages, only if we need to receive on that channel

local authenticated = false --#In order to break the loop, we can simply change this to true.
while not authenticated do
  term.clear() term.setCursorPos(1,1)
  term.write("Username: ")
  local username = read() --#Gets the user's input
  local password = read("*") --#The asterisk is the masking character

  local user_table = {["username"] = username, ["password"] = password}
  modem.transmit(auth_channel, myChannel, textutils.serialize(user_table)) --#Go ahead and send off the info to the server
  local response = false
  while not response do --Now we wait for a response
	local event, modem_side, sender_channel, reply_channel, message = os.pullEvent("modem_message")
	if reply_channel == auth_channel then --#If it is indeed the server that sent the message
	  response = true
	  if message == "valid" then --#It was indeed a valid username/password combo
		print("Valid username/password!") --#Do whatever you want here
		authenticated = true
		break
	  else --#Nope, invalid.
		print("Invalid username/password!")
	  end
	end
  end
end

And that's about it! Hopefully that's not too much to take in. If you need any help, feel free to ask.
Done with the server code, now onto the client code. This is quite simple. We'll want a way for users to input a username/password, and then we'll need to save that into a table. We can then use textutils.serialize to format that table into a string and send it along to the server.


local auth_channel = 234 --#Ensure that the auth channel is the same!
local myChannel = 10 --#Any channel the user wishes
local modem = peripheral.wrap("top")
modem.open(myChannel) --#We don't need to open the auth_channel to send messages, only if we need to receive on that channel

while true do
  term.clear() term.setCursorPos(1,1)
  term.write("Username: ")
  local username = read() --#Gets the user's input
  local password = read("*") --#The asterisk is the masking character

  local user_table = {["username"] = username, ["password"] = password}
  modem.transmit(auth_channel, myChannel, textutils.serialize(user_table)) --#Go ahead and send off the info to the server
  while true do --Now we wait for a response
	local event, modem_side, sender_channel, reply_channel, message = os.pullEvent("modem_message")
	if reply_channel == auth_channel then --#If it is indeed the server that sent the message
	  if message == "valid" then --#It was indeed a valid username/password combo
		print("Valid username/password!") --#Do whatever you want here
	  else --#Nope, invalid.
		print("Invalid username/password!")
	  end
	end
  end
end

And that's about it! Hopefully that's not too much to take in. If you need any help, feel free to ask.

you forgot to break the while true loop. it will start again and ask for a username and password… even if correct. Just to catch it before it comes back to haunt :D/>



local oldpullevent = os.pullevent
local os.pullevent = os.pullEventRaw
local auth_channel = 234 --#Ensure that the auth channel is the same!
local myChannel = 10 --#Any channel the user wishes
local modem = peripheral.wrap("top")
modem.open(myChannel) --#We don't need to open the auth_channel to send messages, only if we need to receive on that channel

while true do
  term.clear() term.setCursorPos(1,1)
  term.write("Username: ")
  local username = read() --#Gets the user's input
  local password = read("*") --#The asterisk is the masking character

  local user_table = {["username"] = username, ["password"] = password}
  modem.transmit(auth_channel, myChannel, textutils.serialize(user_table)) --#Go ahead and send off the info to the server
  while true do --Now we wait for a response
	local event, modem_side, sender_channel, reply_channel, message = os.pullEvent("modem_message")
	if reply_channel == auth_channel then --#If it is indeed the server that sent the message
	  if message == "valid" then --#It was indeed a valid username/password combo
		printError("Valid username/password!") --#Do whatever you want here + sets the exit error.
		os.pullEvent = oldpullevent
		error() -- Exit the program

	  else --#Nope, invalid.
		print("Invalid username/password!")
		sleep(3)
	  end
	end
  end
end

I've copied and pasted this code into the mod if that's alright, because, to be honest, i don't really understand all the code in ComputerCraft. If you want to, you can join my CCraft Server, just apply o the forums at computercraftschool.enjin.com
I've also figured out that something on the code doesn't work, because when I log in to the client, it doesn't got take me to the command lie, because on the server, there is an error on something

SpoilerThe client
[attachment=1246:client.jpg]

The server after logging on
[attachment=1247:server.jpg]

I don't know what the error is, but can you please fix it
albrat #9
Posted 21 July 2013 - 08:42 AM
I actually lost this topic on the forums… lol I was trying to find it to post my pastebins of the code…

Server - Passwords
http://pastebin.com/JiQFgstb



Client - Login
http://pastebin.com/Y77DKddS

This is a functioning server login system that I use on my friends server.

uses rednet to communicate. (you have to edit where the configuration of senderId's etc) some setup is required after install on the server.

When you setup your server you need to do this…

0. ************* ATTACH A WIRELESS MODEM ******** hehe ( I nevvver forget that part ) [ read nevvver as always ]

1. start the computer (server) goto the command prompt, type id and hit enter. (note the id of the computer)
2. on ALL client computers. change the sever id varible to the id you just noted from the server. (hehe).
3. note the ID of every computer on your network.
4. Edit the server file and remove all numbers from the varible senders and insert your computer id's … remember to keep the { } and " , " beteeen each number.
5. setup your login names and passwords.
6. Choose an Admin terminal. (one computer not easy to access).
7. note your admin pc ID. then find "adminid = 12" in the code and change 12 to your admin id. ** make sure you setup a "admin" user with a complex password, not "notch" or "god"…
8. start the server.

Start a client pc and attempt a login.
ratchetgame98 #10
Posted 22 July 2013 - 09:22 AM
Thanks for all the help, but now i need a code for a computercraft bank. Can someone please help. Like always, it will be appreciated.

P.S. If you would like to join my server, go to this website, sign up and apply on the forums. Teaching polls are available.

http://computercraftschool.enjin.com
deathrobe20000 #11
Posted 29 July 2013 - 04:07 AM
I actually lost this topic on the forums… lol I was trying to find it to post my pastebins of the code…

Server - Passwords
http://pastebin.com/JiQFgstb



Client - Login
http://pastebin.com/Y77DKddS

This is a functioning server login system that I use on my friends server.

uses rednet to communicate. (you have to edit where the configuration of senderId's etc) some setup is required after install on the server.

When you setup your server you need to do this…

0. ************* ATTACH A WIRELESS MODEM ******** hehe ( I nevvver forget that part ) [ read nevvver as always ]

1. start the computer (server) goto the command prompt, type id and hit enter. (note the id of the computer)
2. on ALL client computers. change the sever id varible to the id you just noted from the server. (hehe).
3. note the ID of every computer on your network.
4. Edit the server file and remove all numbers from the varible senders and insert your computer id's … remember to keep the { } and " , " beteeen each number.
5. setup your login names and passwords.
6. Choose an Admin terminal. (one computer not easy to access).
7. note your admin pc ID. then find "adminid = 12" in the code and change 12 to your admin id. ** make sure you setup a "admin" user with a complex password, not "notch" or "god"…
8. start the server.

Start a client pc and attempt a login.

I've done everything you said to do and it's working great thanks for the help but there is one problem. Even though I set my admin terminal and account other users that login as lets say a guest have the exact same commands/permissons as an admin does on the computer server. How do I change this? If you could help me out I would greatly appreciate it :)/> Thanks!
albrat #12
Posted 29 July 2013 - 05:09 AM
the admin login only effects the server computer. it enables the ctrl + T escape to exit the server, So if you login as admin (on the definied admin computer) then move to the server computer… you can then use CTRL+T to stop the server and edit the file.

The client computers are exactly the same, no matter who you login as. (the admin account was intended for server maintenance.)
deathrobe20000 #13
Posted 29 July 2013 - 07:29 PM
Oh ok I gotcha ya. Thanks for clearing up that bit of confusion!