Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1248
  • Last Modified:

Getting PHP Login Script to Remember the Session

Hi all, hope you can help me with this, was recommended this site by a contractor at work.

I have an issue where by my code does not remember a session through login, I can get the session displaying the data I request from the database and display it on the page but when browsing away from the page to another area of the website or another url the session is ultimately lost.

Rather than using seperate pages to gather the information I wanted to use the login form with the extension ?login=yes or false when requiring log out.

An example of the page is here:- http://www.ezegaming.com/SiteDevelopment/Index.php

I have setup temporary login details for you to be able to see my fristration.
Username = 'ADMIN EDIT'
Password = 'ADMIN EDIT'

If you login you will see that the correct information is brought back from the database, but when clicking on the 'Home' tab which redirects to the same page the login form is on the session is lost, can anyone help and spot why on the code i've attached??

NOTE: I have the start_session() command already on the main index page, I am calling this script via login.php as an include on the index page.

Thanks in advance for the help and support,
Tim

EDITS MADE
VEE_MOD
<div style="position:absolute; right:10px; top:23px; height: 100px; width: 330px; background-color:#000">
	
		<?php
			// database credentials
			$host="db1208.oneandone.co.uk"; // Host name
			$username="userName"; // Mysql username
			$password="password"; // Mysql password
			$db_name="dbName"; // Database name
					
			 // username and password sent from form
			$myusername=$_POST['myusername'];
			$mypassword=$_POST['mypassword'];
			$login=$_GET['login'];
									
			if($login=='yes'){
				// Connect to server and select databse.
				$con=mysql_connect("$host", "$username", "$password")or die("cannot connect");
				mysql_select_db("$db_name")or die("cannot select DB");
												
				$saltsql="SELECT t1.converge_pass_salt FROM ibf1_members_converge AS t1 INNER JOIN ibf1_members AS t2 ON t1.converge_id = t2.id WHERE t2.name='$myusername'";
				$saltresult=mysql_query($saltsql);
				$saltresult=mysql_result($saltresult, 0);
				
				$namesql="SELECT members_display_name FROM ibf1_members WHERE name='$myusername'";
				$nameresult=mysql_query($namesql);
				$nameresult=mysql_result($nameresult, 0);
				
				$avatarpath="SELECT t3.avatar_location FROM ibf1_members_converge AS t1 INNER JOIN ibf1_members AS t2 ON t1.converge_id = t2.id INNER JOIN ibf1_member_extra AS t3 ON t2.id = t3.id WHERE t2.name='$myusername'";
				$avatarpathresult=mysql_query($avatarpath);
				$avatarpathresult=mysql_result($avatarpathresult, 0);
				
				$avatartype="SELECT t3.avatar_type FROM ibf1_members_converge AS t1 INNER JOIN ibf1_members AS t2 ON t1.converge_id = t2.id INNER JOIN ibf1_member_extra AS t3 ON t2.id = t3.id WHERE t2.name='$myusername'";
				$avatartyperesult=mysql_query($avatartype);
				$avatartyperesult=mysql_result($avatartyperesult, 0);
				
				if ($avatartyperesult!='') {
				if ($avatartyperesult=='url') $avatarpathresult = $avatarpathresult;
				if ($avatartyperesult=='local') $avatarpathresult = "http://www.ezegaming.com/Forum/style_avatars/defaultavatar.jpg";
				if ($avatartyperesult=='upload') $avatarpathresult = "http://www.ezegaming.com/Forum/uploads/$avatarpathresult";
				}
				   
				else $avatarpathresult = 'http://www.ezegaming.com/Forum/style_avatars/defaultavatar.jpg';
							
				$messagecount="SELECT new_msg FROM ibf1_members WHERE name='$myusername'";
				$messagecountresult=mysql_query($messagecount);
				$messagecountresult=mysql_result($messagecountresult, 0);
				
				$awardlocation="SELECT award_image FROM ibf1_awards AS t1 INNER JOIN ibf1_members AS t2 ON t1.username = t2.id WHERE t2.name='$myusername' LIMIT 0,5";
				$awardlocationresult=mysql_query($awardlocation);
	
				echo "<div style='position:absolute; top:60px; left:88px;'>";
				echo "<table>";
	
				while($awardlist = mysql_fetch_array($awardlocationresult))
				{
					echo "<td>";
					echo "<img style='height:25px; width:25px; padding-left:0px;' src='http://www.ezegaming.com/Forum/style_images/awards/".$awardlist['award_image']."'>";
					echo "</td>";
				}
							
				echo "</table>";
				echo "</div>";
				
				echo "<div style='position:absolute; top:44px; left:88px;'>";
				echo "<table>";
				
				$medaltotalcount="SELECT count(username) FROM ibf1_awards AS t1 INNER JOIN ibf1_members AS t2 ON t1.username = t2.id WHERE t2.name='$myusername'";
				$medaltotalcountresult=mysql_query($medaltotalcount);
				$medaltotalcountresult=mysql_result($medaltotalcountresult, 0);
				
				{
				echo "<td>";
				echo "Latest Medals Awarded: ($medaltotalcountresult in total)";
				echo "</td>";
				}
				
				echo "</table>";
				echo "</div>";
	
				// encrypt password
				$encrypted_mypassword = md5( md5( $saltresult ) . md5( $mypassword ) );
				
				$sql="SELECT * FROM ibf1_members_converge AS t1 INNER JOIN ibf1_members AS t2 ON t1.converge_id = t2.id WHERE t2.name='$myusername' AND t1.converge_pass_hash='$encrypted_mypassword'";
				$result=mysql_query($sql);
				
				// Mysql_num_row is counting table row
				$count=mysql_num_rows($result);
				// If result matched $myusername and $mypassword, table row must be 1 row
							
				if($count==1){
				// Register $myusername, $mypassword and redirect to file "login_success.php"
				$_SESSION['myusername']=$myusername;
				}
				else {
				echo "<div style='position:absolute; right:5px; top:2px; color:red;'>Wrong Username or Password</div>";
				}
			}
			?>
			
		<?php if (isset($_SESSION['myusername'])) { ?>
		<form name="form1" method="post" action="Index.php?login=no">
		<div style="position:absolute; right:30px; bottom:12px;">Logout</div><div style="position:absolute; bottom:7px; right:7px;"><input type="image" src="http://www.ezegaming.com/SiteDevelopment/Images/submit.png" name="Submit" value="Login"></div>
		<?php
			$con=mysql_connect("$host", "$username", "$password")or die("cannot connect");
			mysql_select_db("$db_name")or die("cannot select DB");
		
			$namesql="SELECT members_display_name FROM ibf1_members WHERE name='$myusername'";
			$nameresult=mysql_query($namesql);
			$nameresult=mysql_result($nameresult, 0);
			
			$avatarpath="SELECT t3.avatar_location FROM ibf1_members_converge AS t1 INNER JOIN ibf1_members AS t2 ON t1.converge_id = t2.id INNER JOIN ibf1_member_extra AS t3 ON t2.id = t3.id WHERE t2.name='$myusername'";
			$avatarpathresult=mysql_query($avatarpath);
			$avatarpathresult=mysql_result($avatarpathresult, 0);
			
			$avatartype="SELECT t3.avatar_type FROM ibf1_members_converge AS t1 INNER JOIN ibf1_members AS t2 ON t1.converge_id = t2.id INNER JOIN ibf1_member_extra AS t3 ON t2.id = t3.id WHERE t2.name='$myusername'";
			$avatartyperesult=mysql_query($avatartype);
			$avatartyperesult=mysql_result($avatartyperesult, 0);
			
			if ($avatartyperesult!='') {
			if ($avatartyperesult=='url') $avatarpathresult = $avatarpathresult;
			if ($avatartyperesult=='local') $avatarpathresult = "http://www.ezegaming.com/Forum/style_avatars/defaultavatar.jpg";
			if ($avatartyperesult=='upload') $avatarpathresult = "http://www.ezegaming.com/Forum/uploads/$avatarpathresult";
			}
			   
			else $avatarpathresult = 'http://www.ezegaming.com/Forum/style_avatars/defaultavatar.jpg';
						
			$messagecount="SELECT new_msg FROM ibf1_members WHERE name='$myusername'";
			$messagecountresult=mysql_query($messagecount);
			$messagecountresult=mysql_result($messagecountresult, 0);
			
			$awardlocation="SELECT award_image FROM ibf1_awards AS t1 INNER JOIN ibf1_members AS t2 ON t1.username = t2.id WHERE t2.name='$myusername' LIMIT 0,5";
			$awardlocationresult=mysql_query($awardlocation);
 
			echo "<div style='position:absolute; top:60px; left:88px;'>";
			echo "<table>";
 
			while($awardlist = mysql_fetch_array($awardlocationresult))
			{
				echo "<td>";
				echo "<img style='height:25px; width:25px; padding-left:0px;' src='http://www.ezegaming.com/Forum/style_images/awards/".$awardlist['award_image']."'>";
				echo "</td>";
			}
						
			echo "</table>";
			echo "</div>";
			
			echo "<div style='position:absolute; top:44px; left:88px;'>";
			echo "<table>";
			
			$medaltotalcount="SELECT count(username) FROM ibf1_awards AS t1 INNER JOIN ibf1_members AS t2 ON t1.username = t2.id WHERE t2.name='$myusername'";
			$medaltotalcountresult=mysql_query($medaltotalcount);
			$medaltotalcountresult=mysql_result($medaltotalcountresult, 0);
			
			mysql_close($con);
			
			{
			echo "<td>";
			echo "Latest Medals Awarded: ($medaltotalcountresult in total)";
			echo "</td>";
			}
			
			echo "</table>";
			echo "</div>";
					 
			echo "<div style='position:absolute; left:80px; top:10px;'>Welcome back, $nameresult!</div>";
			echo "<div style='position:absolute; left:80px; top:27px;'><img src='http://www.ezegaming.com/SiteDevelopment/Images/pm_small.png'><a href='http://www.ezegaming.com/Forum/index.php?act=Msg&CODE=01'> ($messagecountresult) New Messages</a></div>";
			echo "<div style='position:absolute; left:205px; top:27px;'>| <img src='http://www.ezegaming.com/Forum/style_images/default/my_controls.png' style='width:12px; height:8px;'><a href='http://www.ezegaming.com/Forum/index.php?act=UserCP&CODE=00'> My Controls</a></div>";
			echo "<div style='position:absolute; left:-3px; top:10px;'><img src='$avatarpathresult' style='height:80px; width=80px;'</div>";
		?>
		</form>
	<?php } else { ?>
		<form name="form1" method="post" action="Index.php?login=yes">
		<div style="position:absolute; top:10px; left:10px;">
		Login to EzEGaming
		</div>
		<div style="position:absolute; top:30px; left:10px;">
		Username:
		</div>	
		<div style="position:absolute; top:45px; left:10px;">
		<input name="myusername" type="text" id="myusername" style="height:15px; width:120px;">
		</div>	
		<div style="position:absolute; top:30px; left:150px;">
		Password:
		</div>	
		<div style="position:absolute; top:45px; left:150px;">
		<input name="mypassword" type="password" id="mypassword" style="height:15px; width:120px;">
		</div>	
		<div style="position:absolute; top:45px; left:280px;">
		<input type="image" src="http://www.ezegaming.com/SiteDevelopment/Images/submit.png" name="Submit" value="Login">
		</div>	
		</form>
		<div style="position:absolute; top:75px; left:10px;">
		  <a href="http://www.ezegaming.com/Forum/index.php?act=Reg&CODE=00">Join EzEGaming</a> | <a href="#">Forgot Login</a> | <a href="#">Help</a>		
		</div>
			<?php } 
				//If a session, allow logout
					if($login=='no'){
					unset($_SESSION['myusername']);
					}
				?>
	</div>

Open in new window

0
EzEApostle
Asked:
EzEApostle
  • 11
  • 11
  • 4
  • +1
1 Solution
 
Ray PaseurCommented:
The general case is this:

session_start()

if ($_SESSION["user_name" != '') { process page } else { redirect to login page }

Login page has a form, does a table lookup and upon satisfying conditions of User Name and Password, sets $_SESSION["user_name"] to show the user is logged in.

You must use session_start() on EVERY page and it must be the first thing on the page.
0
 
CoyotesITCommented:
I believe that you need to make sure you are initializing the session on the other pages.

http://us2.php.net/session_start

it is best to just include this in your header. That should take care of it though.

Good luck!
0
 
Ray PaseurCommented:
Also, now that you've posted a password in a public forum, you should change the password on that database ASAP!

It looks like you're doing a lot of processing that is not related to the login in the code sample above.  Simplifying that will undoubtedly help keep things easier to understand.  Consider getting this book and following the examples: http://www.sitepoint.com/books/phpmysql1/

It has great examples, and it's useful both as a reference and a tutorial.

If you are suspicious that the session handler is not working correctly, run this code snippet.

Good luck, ~Ray
<?php
session_start();
if (isset($_POST[submit])) {
	if(!isset($_SESSION['cheese'])) {
		$_SESSION['cheese'] = 1;
	} else {
		$_SESSION['cheese']++;
	}
}
?>
<html><head><title>Session Test</title></head>
<body>
Current Session Variable value is: <?= $_SESSION['cheese'] ?> <br/>
<form method="post">
<input type=submit value=click name=submit>
</form>
</body>
</html>

Open in new window

0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
mriz81Commented:
Have you included session_start(); in your index page? in which your code ( login.php )  is called?
Just remember to include session_start(); in each of your file including login file.

Tip: some times including session_start(); twice may give you a warning that session is already initialized. To avoid this use @session_start();
0
 
EzEApostleAuthor Commented:
I have the session_start() at the top of the login.php and the index.php and it still isn't remembering the login details.

If you login using the test details above I provided and then click on the home button, basically: http://www.ezegaming.com/SiteDevelopment/Index.php you will notice the session is lost.

I'm relativly new to php, so please bare with me if I'm missing something obvious :(

Thanks
Tim
0
 
Ray PaseurCommented:
Add this code to the page somewhere in the footer so we can see what's afoot.  Thanks.  I'll go login.  It will be easier for us to debug if we can see more of the underlying data.  ~Ray
echo "<pre>";
var_dump($_SESSION);
echo "</pre>";

Open in new window

0
 
EzEApostleAuthor Commented:
Thanks, I've added that code to the page which shows in the banner next to the login area
0
 
Ray PaseurCommented:
I assume you did not mean to close this question, right?  I can see the session data, so now we can start debugging.  Put the code snippet I posted above (search this page for cheese) on your server and post a link to it.  Standing by, ~Ray
0
 
EzEApostleAuthor Commented:
yes this was in error, I was trying to remove my username and password from the question but couldnt amend it!

I have uploaded your file here:- http://www.ezegaming.com/SiteDevelopment/test.php

Thanks
0
 
mriz81Commented:
can u please attach your login.php file with your reply?

Thanks
0
 
Ray PaseurCommented:
Thanks, I tested the session test script above and it's working fine, so something is munging your session variable named "myusername" - the rest of the session remains intact.

I think we are going to need to see all of Index.php - the error is not occurring in the code snippet from your original post.
0
 
EzEApostleAuthor Commented:
I'll attach the Index.php file but I can't see how this will be an issue as its only including the file, does it look ok to you?

Thanks
Tim

index.txt
0
 
Ray PaseurCommented:
Thanks, Tim.  I'm looking at it now.  We might also want to see this: Includes/login.php
0
 
EzEApostleAuthor Commented:
All the Index page does is include the login.php (code above) here:-

<?php include("Includes/login.php"); ?>
0
 
Ray PaseurCommented:
OK, Roger that.
0
 
EzEApostleAuthor Commented:
login.php:-


login.txt
0
 
Ray PaseurCommented:
I'm thinking that something about the use of the GET variable login=yes is causing the trouble.  This is a very unusual way of handling the login.  I will look a little more later on.  In the intervening time, you might want to scan your source code for the string myusername and see where it is being accessed.  Also scan for $_SESSION - be on the lookout for something like $_SESSION = $old_session or some other wholesale replacement of the variables.
0
 
mriz81Commented:
can you put remarks on following line in login.php for a moment please?

unset($_SESSION['myusername']);

I am afraid session is unsetting at somewhere  and this might be doing this.
0
 
EzEApostleAuthor Commented:
                 <?php }
                        //If a session, allow logout
                              if($login=='no'){
                              //unset($_SESSION['myusername']);
                              }
                        ?>

Done and uploaded

Thanks
Tim
0
 
EzEApostleAuthor Commented:
The problem still persists, any other ideas anyone?
Thanks
Tim
0
 
mriz81Commented:
No solution working. You will have to give limited ftp access to debug the problem.
0
 
Ray PaseurCommented:
Tim, I'm looking at this code on the second day and still finding it confusing.  I would rewrite it if it were up to me to be responsible for the code.  Your index.php script should not be handling the login - that should be done elsewhere in a login script.  There should be only ONE place that $_SESSION["myusername"] is modified, and obviously the logic of this script or some other script is modifying it incorrectly.

I've attached some functions and a login, logout script below.  Not all of the local functions are there, so it may have a bit of "pidgin code" but you should be able to follow the principles.  With this kind of setup, you simply include the statement access_control() in your script and you're protected.  Obviously, you could also write a "check_access_control()" function if you wanted to mix protected and unprotected items on the same page.

Good luck, ~Ray
/* ************************************************************************* */
function validate_login($email, $pword) {
 
	global $db_connection, $my_dbt_prefix;
 
	$_SESSION["email"]	= '';
	$_SESSION["a_key"] 	= '';
 
	$now	= date('Y-m-d H:i:s');
 
	$email	= trim(strtolower(get_clean_email_string($email)));
	$pword	= trim(strtolower(get_clean_email_string($pword)));
	$pword	= substr($pword,0,16);
 
	$sql	= "SELECT * FROM {$my_dbt_prefix}_ANGLERS WHERE angler_email = \"$email\" AND angler_pword = \"$pword\" AND angler_expdt > \"$now\" ORDER BY _key DESC LIMIT 1";
	if (!$result = mysql_query("$sql", $db_connection)) { non_fatal_query_error($sql);
return false; }
	while ($row = mysql_fetch_assoc($result)) {
		$_SESSION["email"]	= $row["angler_email"];
		$_SESSION["a_key"]	= $row["_key"];
		$_SESSION["a_exp"]	= $row["angler_expdt"];
	}
	if ($_SESSION["email"] == '') {
return false; } else {
return true; }
}
/* ************************************************************************* */
 
/* ************************************************************************* */
function error_halt($message) {
?>
	<html><head>
	<script language="JavaScript">
	<!--
		alert("<?=$message?>");
		history.back();
	//-->
	</script></head><body></body></html>
<? exit;
}
/* ************************************************************************* */
 
/* ************************************************************************* */
//
// ACCESS CONTROL FUNCTION
//
function access_control($public='No') {
	global $db_connection, $my_dbt_prefix;
	global $my_login_cookie;
	global $my_admin_cookie;
 
	if (trim(strtolower($public)) == 'public') {
		header("Cache-control: private");
return true; 
}
 
	// IF SESSION, USER ALREADY LOGGED IN
	if ( ($_SESSION["a_key"] != '') && ($_SESSION["email"] != '') ) {
		header("Cache-control: private");
return true; 
}
 
 
	// ESTABLISH ENTRY PAGE
	if (empty($_SERVER["HTTPS"])) { $protocol = 'http://'; } else { $protocol = 'https://'; }
	$_SESSION["my_entry_uri"] = $protocol . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
 
	$login_page = 'login.php';
 
	header("Location: $login_page");
exit();
}
/* ************************************************************************* */
 
 
 
 
<?php // login.php
 
$config_page= getcwd() . '/_config.php'; require_once($config_page);
$page_title	= 'Log In';
 
$eMail	= get_clean_email_string($_POST['eMail']);
$pWord	= get_clean_email_string($_POST['pWord']);
 
$login	= $eMail . $pWord;
if ($login != '') {
	if (!validate_login($eMail, $pWord)) { error_halt("Please log in with your email address and password"); }
}
 
// REQUEST LOGIN
if ($_SESSION['email'] == '') {
 
	top_of_page();
	?>
 
	<form name="LoginForm" action="<?=$_SERVER["REQUEST_URI"]?>" method="POST">
	<table id="reg_table" cellpadding="1" cellspacing="1" border="0">
 
	<tr><td colspan="2"><h2>Please log in</h2></td></tr>
 
	<tr>
	<td align="right"><span class="required">eMail Address:</span> &nbsp; </td>
	<td><input type="text" size="30" name="eMail" value="<?=$eMail?>" /></td>
	</tr>
 
	<tr>
	<td align="right"><span class="required">Your Password:</span> &nbsp; </td>
	<td><input type="password" size="30" name="pWord" value="<?=$pWord?>" /></td>
	</tr>
 
	<tr>
	<td align="right">&nbsp; </td>
	<td><input type="submit" name="_submit" value="Log In" /></td>
	</tr>
 
	</table>
	</form>
 
	<?php
	end_of_page('N');
 
} else {
// LOGIN SUCCESSFUL
	$my_entry_page	= $_SESSION["my_entry_uri"];
	if (ereg("login\.php$", $my_entry_page)) { $my_entry_page = str_replace('login.php', 'index.php', $my_entry_page); }
	header("Location: $my_entry_page");
	exit;
}
?>
 
 
 
<?php // logout.php
$_SESSION = array();
if (isset($_COOKIE[session_name()])) {
   setcookie(session_name(), '', time()-42000, '/');
}
session_destroy();
header("Location: /");
exit;
?>

Open in new window

0
 
EzEApostleAuthor Commented:
Thanks Ray, I feel there is no further choice but to try and re-write the code, especially if you guys cant figure it out.

Thanks for all the help, I've awarded you the points for providing the above code.

Tim
0
 
EzEApostleAuthor Commented:
Thanks for all the help
0
 
Ray PaseurCommented:
Thanks for the points, Tim.  Best of luck!
0
 
EzEApostleAuthor Commented:
I''ve re-written the php files and I'm happy to say the login now works!! :)

I only have one thing I need help with though, as I am now using other files as the method e.g. checklogin.php on the forum action and logout.php to handle the logout (detroying the session and returning to the main page) I can't find out for the life of me how to display the 'Username or password is incorrect" if the user enters incorrect detail above the form, it's currently displaying on the check login page due to the method.

Can you give any suggestions??

Current code of checklogin.php:-


// Connect to server and select databse.
mysql_connect("$host", "$username", "$password")or die("cannot connect");
mysql_select_db("$db_name")or die("cannot select DB");
 
// Define $myusername and $mypassword
$myusername=$_POST['myusername'];
$mypassword=$_POST['mypassword'];
 
// To protect MySQL injection (more detail about MySQL injection)
$myusername = stripslashes($myusername);
$mypassword = stripslashes($mypassword);
$myusername = mysql_real_escape_string($myusername);
$mypassword = mysql_real_escape_string($mypassword);
 
$saltsql="SELECT t1.converge_pass_salt FROM ibf1_members_converge AS t1 INNER JOIN ibf1_members AS t2 ON t1.converge_id = t2.id WHERE t2.name='$myusername'";
$saltresult=mysql_query($saltsql);
$saltresult=mysql_result($saltresult, 0);
 
$encrypted_mypassword = md5( md5( $saltresult ) . md5( $mypassword ) );
 
$sql="SELECT * FROM ibf1_members_converge AS t1 INNER JOIN ibf1_members AS t2 ON t1.converge_id = t2.id WHERE t2.name='$myusername' AND t1.converge_pass_hash='$encrypted_mypassword'";
$result=mysql_query($sql);
 
// Mysql_num_row is counting table row
$count=mysql_num_rows($result);
// If result matched $myusername and $mypassword, table row must be 1 row
 
if($count==1){
// Register $myusername, $mypassword and redirect to file "login_success.php"
session_register("myusername");
session_register("mypassword");
header("location:Index.php");
}
else {
echo "<div style='position:absolute; right:5px; top:2px; color:red;'>Wrong Username or Password</div>";
}
 
ob_end_flush();
?>

Open in new window

0
 
Ray PaseurCommented:
You might consider adding a field to $_SESSION that says in effect "bad login" - then you could display the appropriate message on any page until a successful login removed the bad login field.

Also, it would be good practice to put this statement right after the header("location:Index.php"); because if you don't explicitly exit the script, it will go right on executing instructions.  In other words, header() is just an inline command, so when you want to redirect, you need to stop the script with a separate command.

HTH, ~Ray
exit;

Open in new window

0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 11
  • 11
  • 4
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now