How to transfer SESSION created in soap server to soap client code? - php

I've created a non-wsdl soap server with PHP to run functions from all servers I own. There are bunch of problems on this as you can see from my profile but this I hope is solvable. I cannot transfer SESSION data between server and client.
Already used
$server->setPersistence(SOAP_PERSISTENCE_SESSION);
and set session_id manually
session_id ('ID');
session_start ();
but no luck to transfer SESSION data to client.
Is there a way to transfer SESSION data created on soap-server.php to soap-client.php?

Given this soap server
class MyClass
{
public function __construct(){
session_start();
}
public function login( $user )
{
$_SESSION['user'] = $user;
return true;
}
public function getUserName()
{
return isset( $_SESSION['user'] ) ? $_SESSION['user'] : false;
}
}
$server = new SoapServer( null, array( 'uri' => 'http://localhost/scratch/soap.server.php' ) );
$server->setClass('MyClass');
$server->handle();
And this soap client
$url = 'http://localhost/scratch/soap.server.php';
$config = array( 'location' => $url, 'uri' => $url );
// Call the "login" function to set the user name
$firstClient = new SoapClient(null, $config);
$firstClient->login( array( 'MyUserName' ) ); // ONLY CALL LOGIN ONCE
var_dump( $firstClient->getUserName() ); // TRUE
// Track the cookies
$cookies = $firstClient->__getCookies();
// Second Client fails because we didn't set cookies
$secondClient = new SoapClient(null, $config);
var_dump( $secondClient->getUserName() ); // FALSE
// Works because we've set cookies from the first request
$thirdClient = new SoapClient(null, $config );
$thirdClient->__setCookie( 'PHPSESSID', $cookies['PHPSESSID'][0] );
var_dump( $thirdClient->getUserName() ); // TRUE
You can see I am creating three seperate soap clients, the first performs the login, you can see that the subsequent getUserName() work because we're using the same connection context and its re-using the initial cookies internally.
The second client is independent and has no knowledge of the existing session and fails as expected.
the third client injects the cookie from the first client, and is able to track the username through the session and getUserName() is able to resume without the login() function.
Ideally you would automate the injection of the cookie programmatically instead of my "hard coding" for the purpose of this test
So from here, you have to manage the cookies for the soap client yourself.
If you want the session data itself, there is nothing stopping you from creating an exporting function... eg getSessionData in this example
class MyServerClass
{
public function __construct(){
session_start();
}
public function login( $user )
{
$_SESSION['user'] = $user;
$_SESSION['SomeObject'] = new stdClass();
$_SESSION['SomeObject']->foo = 'bar';
return true;
}
public function getSessionData()
{
return $_SESSION;
}
}

Related

How to access a PHP variable from one function in another function

I have already written an application in a procedural way and am trying to move into into a Laravel framework. I'm having trouble with the SOAP exchange section as I am getting an ID value that authenticates the user but cannot access that value (as a cookie) later in the program to authenticate the search.
Here is my code so far:
<?php namespace App;
use Artisaninweb\SoapWrapper\Facades\SoapWrapper;
use Illuminate\Http\RedirectResponse;
class SoapController {
private $auth_response;
private $cookie;
private $search_client;
private $search_response;
public function soapExchange() {
// create SOAP client and add service details
SoapWrapper::add(function ($service) {
$service
->name('WoSAuthenticate')
->wsdl('http://search.webofknowledge.com/esti/wokmws/ws/WOKMWSAuthenticate?wsdl')
->trace(true)
->cache(WSDL_CACHE_NONE);
});
SoapWrapper::service('WoSAuthenticate', function($service) {
// call authenticate() method to get SID cookie
$auth_response = $service->call('authenticate', []);
$cookie = $auth_response->return;
// test for cookie return
// print($cookie);
});
// create SOAP client and add service details
$search_client = new SoapWrapper;
$search_client::add(function ($service) {
$service
->name('WoSSearch')
->wsdl('http://search.webofknowledge.com/esti/wokmws/ws/WokSearch?wsdl')
->trace(true)
->cache(WSDL_CACHE_NONE);
});
if (isset($auth_response->return)) {
// if there is an SID returned then add it to the cookie attribute of the search client
$search_client->__setCookie('SID', $cookie);
} else {
// route to relevant view to display throttle error
return redirect('throttle');
}
}
}
I am successfully retrieving the response from the Web API call and getting a code to authenticate the user, saved as $cookie. However, I need then to create another SoapWrapper for performing the search and this needs the ID code attached by using the __setCookie method. If nothing is returned by the authenticate call then it redirects to an error message via throttle.blade.php elsewhere.
Surely there is a way to return a value created from a function so that it can be used elsewhere?
** EDIT **
Looked into employing SoapClient instead and including all operations within a single function. It all relates to a specific Web API anyway so I guess separation of concerns is not so much of an issue. FYI the new class I am trying is this:
<?php namespace App\Models;
use SoapClient;
use Illuminate\Http\RedirectResponse;
class SoapWrapper {
public function soapExchange() {
// set WSDL for authentication and create new SOAP client
$auth_url = "http://search.webofknowledge.com/esti/wokmws/ws/WOKMWSAuthenticate?wsdl";
// array options are temporary and used to track request & response data
$auth_client = #new SoapClient($auth_url);
// set WSDL for search and create new SOAP client
$search_url = "http://search.webofknowledge.com/esti/wokmws/ws/WokSearch?wsdl";
// array options are temporary and used to track request & response data
$search_client = #new SoapClient($search_url);
// run 'authenticate' method and store as variable
$auth_response = $auth_client->authenticate();
// call 'setCookie' method on '$search_client' storing SID (Session ID) as the response (value) given from the 'authenticate' method
// check if an SID has been set, if not it means Throttle server has stopped the query, therefore display error message
if (isset($auth_response->return)) {
$search_client->__setCookie('SID',$auth_response->return);
} else {
return Redirect::route('throttle');
}
}
}
Maybe try $GLOBALS?
<?php
$GLOBALS[data] = "something";
function abc(){
echo $GLOBALS[data];
}
?>
use Artisaninweb\SoapWrapper\Facades\SoapWrapper;
class SoapController extends Controller {
public $resultSoapStatus;
public $resultSoapAuthority;
public function heySoap{
SoapWrapper::add(function ($service) ...
$data = [
'MerchantID' => $MerchantID,
'Amount' => $Amount,
'Description' => $Description,
'Email' => $Email,
'Mobile' => $Mobile,
'CallbackURL' => $CallbackURL
];
SoapWrapper::service('test', function ($service) use ($data) {
$resultSoap = $service->call('PaymentRequest', [$data]);
$this->resultSoapStatus = $resultSoap->Status;
$this->resultSoapAuthority = $resultSoap->Authority;
});
if($this->resultSoapStatus == 100 && strlen($this->resultSoapAuthority) == 36)
{
//Do Something
}
else
{
return Redirect::back();
}
}
}
Enjoy bro

"Cannot set session ID after the session has started." while testing form

I'm writing unit tests for my application. I wrote a function to login different user (to test user levels) and a function to generate valid or invalid form data (to test my form handling).
When the test submits a form, it throws an exception:
Uncaught PHP Exception LogicException: "Cannot set session ID after the session has started."
I'm using Symfony 2.6.4. I can't find any usefull information about this error message. The test worked perfectly a while ago.
class ControllerTest extends WebTestCase
{
public $client = null;
public $route = 'home/';
/**
* #var \Doctrine\ORM\EntityManager
*/
public $em;
public function setUp()
{
self::bootKernel();
$this->client = static::createClient();
$this->em = static::$kernel->getContainer()
->get('doctrine')
->getManager()
;
}
public function logIn($role = 'admin')
{
if ($role === 'admin') {
$userId = 20;
} elseif ($role === 'user') {
$userId = 29;
}
$user = $this->em->getRepository('Acme\DemoBundle\Entity\User')->find($userId);
$session = $this->client->getContainer()->get('session');
$firewall = 'main';
$token = new UsernamePasswordToken($user, $user->getPassword(), $firewall);
$session->set('_security_'.$firewall, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
public function getFormData($valid = true)
{
//function to generate (in)valid formdata
}
public function getFormRequest($data, $url)
{
return $this->client->request(
'POST',
$url,
$data,
[],
[
'CONTENT_TYPE' => 'application/json',
'HTTP_X-Requested-With' => 'XMLHttpRequest',
]
);
}
//works OK
public function testNewScenario()
{
$url = $this->baseurl . 'new';
$this->logIn('admin');
$crawler = $this->client->request('GET', $url);
$this->assertEquals(200, $this->client->getResponse()->getStatusCode(), "Unexpected HTTP status code for GET " . $url);
}
public function testValidNewScenario()
{
$this->logIn('admin');
$validData = $this->getFormData(true);
//this function throws the exception
$this->getFormRequest($validData, $this->baseurl);
$this->assertEquals(200, $this->client->getResponse()->getStatusCode(), "Unexpected HTTP status code for POST " . $this->baseurl);
}
}
Here's the relevant part of my config_test.yml:
framework:
test: ~
session:
storage_id: session.storage.mock_file
profiler:
collect: false
What's going on?
I don't know if this is still a problem for the OP as this is an old post, but the same issue had me running around in circles for best part of 3 hours trying to find a way out of it. And seeing as there doesnt seem to be a solution anywhere at all. Heres a possible one.
The problem exists in tests which are trying to create a full login.
Current symfony docs state that its preferred to use basic_http authentication in your tests, but if, like me, you need to be testing access levels youll need to be following this method.
The problem seems to occur when we try to set the cookieJar up. This (for me) always threw an error.
Cannot set session ID after the session has started
the solution as it turns out is reasonably simple. Wrap the cookie set code in a condition that checks for a current session id.
if( !$this->session->getId() ) {
$this->cookie = new Cookie( $this->session->getName(), $this->session->getId() );
$this->client->getCookieJar()->set( $this->cookie ); // <--- this is the problem line
}
its also worth noting that calling $this->session->invalidate() does not solve the issue.
I hope this helps someone and saves them some time.
This effected me on Symfony2.1 (no chance of upgrading), but Ive seen mentions of 2.6 getting it when combined with FOSFacebookBundle (where I believe the issue was fixed).

Laravel Redirect::to() not working

I am creating a twitter log in feature for my project, the oauth step where the user has granted permission for my app to use their data returns the user to the /twitter-auth route, this route in turn initiates this method:
public function auth() {
/* Oauth token */
$token = Input::get('oauth_token');
/* Verifier token */
$verifier = Input::get('oauth_verifier');
/* Request access token */
$accessToken = Twitter::oAuthAccessToken($token, $verifier);
/* Set the session variables from the acccess token above */
Session::set('user_id', $accessToken['user_id']);
Session::set('username', $accessToken['screen_name']);
Session::set('oauth_token', $accessToken['oauth_token']);
Session::set('oauth_token_secret', $accessToken['oauth_token_secret']);
/* Determine if the user already exists in the database, if he/she does, then
only update the user, otherwise, store a new user. Also pass an instance of the
accessToken as flash data in both instances. */
if( User::where('twitter_id', $accessToken['user_id'])->first() == null )
{
$newUser = array(
'username' => $accessToken['screen_name'],
'oauth_token' => $accessToken['oauth_token'],
'oauth_token_secret' => $accessToken['oauth_token_secret'],
'twitter_id' => $accessToken['user_id']
);
User::create( $newUser );
return Redirect::to('/');
}
else
{
$userToUpdate = User::where('twitter_id', Session::get('user_id'))->first();
$userToUpdate->username = $accessToken['screen_name'];
$userToUpdate->oauth_token = $accessToken['oauth_token'];
$userToUpdate->oauth_token_secret = $accessToken['oauth_token_secret'];
$userToUpdate->twitter_id = $accessToken['user_id'];
$userToUpdate->save();
return Redirect::to('/');
}
}
The user is saved/updated as necessary, but the user is not redirected to the home page. This happens with the redirect code both inside and outside of the IF statement. I was wondering if anyone could give me any clues as to why the redirect isn't working?
You are missing a return
your function in this case auth() is returning the Redirect object but is the function calling your auth() function is returning the result back to the controller?
Please make sure that in your controller, you return the Redirect class that is from auth() function.
Just tested your code and works :
let's say you have a UserController :
routes.php
Route::get('twitter-auth',array('as'=>'twitter-auth', 'uses'=>'UserController#twitterAuth'));
UserController
the user model class is just passed by dependency injection, to test this part also.
<?php
class UserController extends BaseController {
public function __construct(User $u){
$this->user = $u;
}
public function twitterAuth(){
return $this->user->auth();
}
}
User model :
I had to modify the code a little to fit my setup also
public function auth(){
/* Oauth token */
$token = Input::get('oauth_token');
/* Verifier token */
$verifier = Input::get('oauth_verifier');
/* Request access token */
//$accessToken = Twitter::oAuthAccessToken($token, $verifier);
//emulate the request of access Token
$accessToken = [
'user_id'=>'11',
'screen_name'=>'fewfewfew',
'oauth_token'=>'12312321',
'oauth_token_secret'=>'12312232323'
];
/* Set the session variables from the acccess token above */
Session::set('user_id', $accessToken['user_id']);
Session::set('username', $accessToken['screen_name']);
Session::set('oauth_token', $accessToken['oauth_token']);
Session::set('oauth_token_secret', $accessToken['oauth_token_secret']);
/* Determine if the user already exists in the database, if he/she does, then
only update the user, otherwise, store a new user. Also pass an instance of the
accessToken as flash data in both instances. */
if( User::where('twitter_id', $accessToken['user_id'])->first() == null )
{
$newUser = array(
'username' => $accessToken['screen_name'],
'oauth_token' => $accessToken['oauth_token'],
'oauth_token_secret' => $accessToken['oauth_token_secret'],
'twitter_id' => $accessToken['user_id']
);
User::create( $newUser );
return Redirect::to('/');
}
else
{
$userToUpdate = User::where('twitter_id', Session::get('user_id'))->first();
$userToUpdate->username = $accessToken['screen_name'];
$userToUpdate->oauth_token = $accessToken['oauth_token'];
$userToUpdate->oauth_token_secret = $accessToken['oauth_token_secret'];
$userToUpdate->twitter_id = $accessToken['user_id'];
$userToUpdate->save();
return Redirect::to('/');
}
}
Let me know if this is what you wanted
Returning a Redirect to execute it is only possible from routes, controller actions and filters. Otherwise you have to call send()
Redirect::to('login')->send();

Session not storing data

I am using Elliot Haughin's twitter oauth library for codeigniter. It can be found here :
https://github.com/elliothaughin/codeigniter-twitter
I have the following code which authenticates a user with twitter and stores session details.
public function login() {
$this->tweet->set_callback(site_url(''));
$this->tweet->login();
$tokens = $this->tweet->get_tokens();
$user = $this->tweet->call('get', 'account/verify_credentials');
$u = $user->screen_name ;
$data = array(
'user' => $u,
'logged_in' => true
);
$this->session->set_userdata($data) ;
}
This is weird but the logged_in variable is saved whereas the user is not. I am not sure where i am going wrong.
have you include SESSION library or autoload it.
Update:
http://codeigniter.com/user_guide/libraries/sessions.html

Best way to use Zend_Oauth_Consumer without cookies and without session

I am developing gadget with tech requirements: "no Cookie, no Session".
I have the following code:
<?php
class LinkedIn
{
private $options;
private $consumer;
private $client;
private $token;
public function __construct($params)
{
// set Zend_Oauth_Consumer options
$this->options = array(
'version' => '1.0',
'localUrl' => $params['localUrl'],
'callbackUrl' => $params['callbackUrl'],
'requestTokenUrl' => 'https://api.linkedin.com/uas/oauth/requestToken',
'userAuthorizationUrl' => 'https://api.linkedin.com/uas/oauth/authorize',
'accessTokenUrl' => 'https://api.linkedin.com/uas/oauth/accessToken',
'consumerKey' => $params['apiKey'],
'consumerSecret' => $params['secretKey']
);
// instanciate Zend_Oauth_Consumer class
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Oauth_Consumer');
$this->consumer = new Zend_Oauth_Consumer($this->options);
}
public function connect()
{
// Start Session to be able to store Request Token & Access Token
session_start ();
if (!isset ($_SESSION ['ACCESS_TOKEN'])) {
// We do not have any Access token Yet
if (! empty ($_GET)) {
// SECTION_IF
// But We have some parameters passed throw the URL
// Get the LinkedIn Access Token
$this->token = $this->consumer->getAccessToken ($_GET, unserialize($_SESSION ['REQUEST_TOKEN']));
// Store the LinkedIn Access Token
$_SESSION ['ACCESS_TOKEN'] = serialize ($this->token);
} else {
// SECTION_ELSE
// We have Nothing
// Start Requesting a LinkedIn Request Token
$this->token = $this->consumer->getRequestToken ();
// Store the LinkedIn Request Token
$_SESSION ['REQUEST_TOKEN'] = serialize ($this->token);
// Redirect the Web User to LinkedIn Authentication Page
$this->consumer->redirect ();
}
} else {
// We've already Got a LinkedIn Access Token
// Restore The LinkedIn Access Token
$this->token = unserialize ($_SESSION ['ACCESS_TOKEN']);
}
// Use HTTP Client with built-in OAuth request handling
$this->client = $this->token->getHttpClient($this->options);
}
}
It's working perfect. But REQUEST_TOKEN stored in SESSION. How can I put it to query string in SECTION_ELSE, and get it back in SECTION_IF? Thanks for all the advice.
The key point is that your system needs to:
1. persist the OAuth tokens between user requests to your server, and
2. tie them to a specific user.
Using a session, whose id comes from either a cookie or from the querystring, is one way to do that.
But if sessions are off the table, then you need some other way to identify the current user and store his OAuth tokens.
If you are truly working in a no-session environment, then how do you even know who the user is? Basic Auth? In the absence of user authentication on your side, I don't see how you'll be able associate OAuth tokens to specific users.

Categories