Share Session Across Multiple Applications [duplicate] - c#

I am trying to share sessions between two web applications, both hosted on the same server. One is a .net 2.0 web forms application the other is as .net 3.5 MVC2 application.
Both apps have their session set up like this:
<sessionState
mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424"
/>
In the webform application I am posting the the session key to the MVC app:
protected void LinkButton1_Click(object sender, EventArgs e)
{
Session["myvariable"] = "dan";
string sessionKey = HttpContext.Current.Session.SessionID;
//Followed by some code that posts sessionKey to the other application
}
I then recieve it in the MVC application and try use the same session like this:
[HttpPost]
public void Recieve(string sessionKey )
{
var manager = new SessionIDManager();
bool redirected;
bool IsAdded;
manager.SaveSessionID(HttpContext.ApplicationInstance.Context, Id, out redirected, out IsAdded);
var myVar = Session["myvariable"];
}
The key is being posted but the session does not seem to get loaded in the MVC app, i.e. sessionKey is null. Can what I am trying to do be done?

I did it this way:
Basically the idea is both apps use native .net sessionState stored in sqlserver. By using the same machine key and making a small tweak to a stored procedure – both apps can share any session keys and/or forms authenication.
Both apps would do something like this in their web.config:
<sessionState mode="SQLServer" sqlConnectionString="Data Source=.\SQLEXPRESS;User Id=test;Password=test;Application Name=AppName" />
<machineKey
validationKey="SOMEKEY"
validation="SHA1" decryption="AES"
/>
Session state db would need to be set up on a database server, that both apps can see.
Docs for doing this:
http://msdn.microsoft.com/en-us/library/ms229862(VS.80).aspx
Command that would need to be run:
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin>aspnet_regsql.exe -E -ssadd --sstype p -S .\SQLEXPRESS
Stored procedure (TempGetAppID) tweak to:
#appId int OUTPUT
AS
-- start change
-- Use the application name specified in the connection for the appname if specified
-- This allows us to share session between sites just by making sure they have the
-- the same application name in the connection string.
DECLARE #connStrAppName nvarchar(50)
SET #connStrAppName = APP_NAME()
-- .NET SQLClient Data Provider is the default application name for .NET apps
IF (#connStrAppName <> '.NET SQLClient Data Provider')
SET #appName = #connStrAppName
-- end change
SET #appName = LOWER(#appName)

The problem is that session keys are scoped to the applications, so two applications having the same session key in fact have separate sessions.
You can do one of two things:
Put both applications as a virtual directory under a common IIS Application. I don't think this is a good idea, but it will work.
Roll your own session data solution for the data you want to share. Possibly using the backend database as the common storage, if you have one that is.
Based on Justin's comment, just to clarify option 2 is not refering to the SQL state managemet for out of process sessions. I mean for you to actually manually manage the shared data for the two sessions, possibly using a database.

You can use a common Machine key to generate same Session ID inside both applications for a given user. Additionally, you should also plan on storing sessions of both applications in a common store such as ASP.NET State Service or a distributed cache.
You can use NCache distributed cache which takes provides session sharing feature between different applications. You specify same Application ID tag for both apps inside session state settings which allows you to share session object provided you have same Session ID generated for both applications.

Related

Redis - Moving from IIS session state

I am trying to understand how to implement redis by replacing all IIS session state values with the redis cache. I have redis working using a docker image. I am using a C# .Net Forms web app. I have included the StackExchange.Redis nuget package and set this up so far.
public class Redis
{
private static readonly Lazy<ConnectionMultiplexer> LazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
var redisConnectionString = ConfigurationManager.AppSettings["RedisConnectionString"];
var options = ConfigurationOptions.Parse(redisConnectionString);
options.AbortOnConnectFail = false;
return ConnectionMultiplexer.Connect(options);
});
public static ConnectionMultiplexer Connection => LazyConnection.Value;
}
But I am confused how to store the user context session key value pairs. By this I mean when I store a key for the user, say "UserId" can the key just be "UserId"? or do I needs to prefix it with a unique user specific context id. I cant find anything on how redis would work based on different users. How does it know the context of the user and hence how to get the correct key?
All I'm reading is that its a hashtable that stores values, which is fine for a single UserId, but I'm going to have lots of users with a UserId?
If anyone can help me understand this, that would be great, thanks you
Ok so after looking at the following link I was able to get it all working
https://learn.microsoft.com/en-us/azure/azure-cache-for-redis/cache-aspnet-session-state-provider
I installed a redis docker image as follows on the command line, replacing your your_long_password_here, you can also just specify port 6379:6379, but I wanted to see what happens if I used another port. The password is important as otherwise it will run in protected mode which means only localhost(loopback) calls can be made, which helps protect it more, as pre version 3.2 this was not the case!
docker run -p 8055:6379 --name redis --restart=always -d redis –-requirepass <your_long_password_here>
The run this command to make sure it was running, you should see that the port has the values you provided
docker container ls
Then in your .net project install the following nuget packagefrom the nuget package manager console or use the GUI package manager. You will need to use .net 4.6.2 for the current version.
Install-Package Microsoft.Web.RedisSessionStateProvider
Once installed comment out or remove this line in your Web.config
<sessionState mode="InProc" timeout="60" />
Then update or change the new provider that the nuget package will have added to your Web.config. This should be inside the system.web tag. Note that I used a connection string as this will not be hosted on azure as of yet, but there are lots of confusing extra options to configure it.
<sessionState mode="Custom" customProvider="MySessionStateStore">
<providers>
<add name="MySessionStateStore"
type="Microsoft.Web.Redis.RedisSessionStateProvider"
connectionString="localhost:8055,password=your_long_password_here"/>
</providers>
</sessionState>
You will need to make sure all the objects that you were storing in the iis session have the [Serializable] attribute as otherwise it wont work and will throw an error.
You should now see that you can run your website seamlessly, and you will now be using the redis cache and no longer the session state.

ASP.NET and C#: connection string in web.config vs connection string stored on Azure

I have a web form developed in ASP.NET and C#. I am storing the connection string to a database in the web.config file like this:
<connectionStrings configSource="MySecrets.config" />
This points to a local file in the same directory as the solution. Debugging locally works, however it is not advisable to commit this file to source control to avoid exposing these secrets.
This article mentions that it is possible to store connection strings on Azure - in the Configurations section of an App Service. The article also says that it's possible to retrieve the connection strings in the code by doing:
dbConn = System.Configuration.ConfigurationManager.AppSettings("myConnStringName")
The article also mentions that "if the application setting(s) happen to already exist in your web.config file, Windows Azure Web Sites will automatically override them at runtime using the values associated with your website. Connection strings work in a similar fashion.
(This assumes that your connection strings are explicit in the web.config file, and if committed to source control, they would be exposed.)
However, in my code, I already have a line with:
dbConn = WebConfigurationManager.ConnectionStrings["myConnStringName"].ConnectionString
Questions:
1) How am I supposed to reconcile these two lines without declaring the same variable (dbConn) twice?
2) How can I not commit MySecrets.config to source control, but at the same time use it when I debug my app locally, while using the connection string stored on Azure when working with the published app?

Operation is not allowed when the object is closed. Updated Visual Basic 2012 to Update 3

My program was working until yesterday. But my company moved to a new domain and I also had to do that. Now I cannot connect to SQL Server, what should I change in my connection string?
Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Pedram;Data Source=DELL_RACK
The error I get for my inserts is:
Operation is not allowed when the object is closed.
By the way, I think I also upgraded my Visual Studio to Update 3. Could this also be the problem?
The connection string will stay the same. It won't change at all. This relies on the user's security context to authenticate to sql server. Therefore, we'll need to fix it so that the users accessing the database are authorized to use the database.
The change will need to be either in how you choose what user is logged in (ie: if this is an asp.net site doing impersonation, or similar process for setting the current user) orby grant login rights to users in the new domain in Sql Server, or both.
You can use SQL Server authentication Mix mode.
For create a Connection String in mix mode use this
Server=myServerAddress;Database=myDataBase;User Id=myUsername;
Password=myPassword;
and en total you can see this link : [http://www.connectionstrings.com/sql-server/][1]
if you use mix mode authentication , change windows permission can not make error in your program.

How to connect to different databases?

I'm currently developing an application based on ASP.NET MVC3, SQL Server 2008 and EF with database first.
My application requires every user to have it's own SQL Server database. These databases all have an identical structure.
My customers are identified with a customercode, e.g. fgt. This code is provided in the url.
I need to know how can I retrieve the customercode from the url and set the connection string accordingly.
Thanks for the help
My idea is to connect to the database once the customercode is retrieved from the URL and then prompt to user to enter his username and password for access data.
But yes, is a good idea to create a database to store the connection string of each customer.
Can anyone write the code that I need for do this please?. I am new to asp. I come from php.
(I'm just learning English. Sorry about the bad grammar)
Try something like this to get started:
string customerCode = Request.QueryString["cust"].ToString();
string myNewConnString = ConfigurationManager
.ConnectionStrings["MyDatabase"]
.ConnectionString
.Replace("[placeholder]", customerCode);
Where your connection string in your .config is something like this. Note that I've assumed you'll place a token to be replaced ([placeholder]).
<add name="MyDatabase"
connectionString="Data Source=192.168.0.1;Initial Catalog=[placeholder];User ID=foo;Password=bar"
providerName="System.Data.SqlClient" />
Suggest that you whitelist your customers and their connection strings.
setup a web service on your side.
your deployed application calls your web service using the customer code.
web service validates the customer code, and returns a valid conn string.
customer's app keeps the conn string in memory (session, cache, whathaveyou).
This would allow you to ensure the conn string is always valid for a given customer code. You'd have fine grain control on access to the database for any reason (non-payment, etc). Your service would have a few hits thanks to any caching that you build in.
maybe sqlshard could help you in using multiple databases?
http://enzosqlshard.codeplex.com/
Sounds like pretty insecure solution. What if customer put another customer code in URL? Where is validated if customer can access that code if you don't have any central database with customer's permissions?
You need authentication and some central store (additional database) where you will validate that user accessing the application has access permissions to provided URL. It will also validate if such database even exists. Next you need just SqlConnectionStringBuilder and use the customer code as a name of database (or part of the name). For security reason each database should have a separate SQL account with permissions to read only from that database. This db account can also be stored with that central storage with encrypted passwords.
There can be additional complexities if you also expect dynamical adding or removing customer codes = databases. That would require high privileged account to manage logins, accounts, databases, etc.
Because you are asking how to get part of Uri it looks like you have almost no experience with ASP.NET MVC and perhaps with everything related. You should definitely ask any more skilled colleague or boss to review your architecture because at this point it looks like you are going to have serious problems and you can develop very insecure application which can significantly harm reputation of your company and your customer.

Asp.net: How session works in a server farm environment

I would like to know in how the Session locking mechanism work and how I can lock a variable and its respective child objects for multiple reads/exclusive write in a server farm environment.
Scenario
The web farm will use 3 Windows 2003 servers, each server as its own app domain for the Web application. The sesion object is saved on SQL Server 2005.
The object to use in my web app is at follows:
MySampleClass = class
{
public string Id;
public Dictionary<string, CustomClass1> Data;
public List<string> Commands;
public CustomClass2 MoreData;
}
where customClass 1 and 2 are business classes that are part of the application.
now in one of the web pages, code will look like:
Session["myObj"] = new MySampleClass();
in other pages:
MySampleClass = (MySampleClass)Session["myObj"];
//Is Session["myObj"] accessed in a multiple reader/exclusive writer mode? if so is it locking just the variable or the whole contents?
MySampleClass.Commands.Add("sample string");
MySampleClass.Commands.RemoveAt(0);
//More CRUD changes
//Are these changes available to other pages as soon as I finish the CRUD changes?
let me know if you need more details
Have a look here under Locking Session-Store Data. Basically, unless your page says it wants read-only session access, the session is locked on the DB and other callers for that session will poll at 1/2sec interval until it is unlocked.
There is also a detailed explanation on "Session State Providers" on msdn.
It covers the algorithm and rules used when using out-of-process session state providers in ASP.NET.

Categories