skip to Main Content

The sample project https://github.com/xingyu217/Redis-nginx-aspnetcore-session
nginx.config:

upstream study_server{
        server localhost:8011 weight=1;
        server localhost:8013 weight=1;
    #server localhost:8014 weight=1;
    #server 172.17.16.147:8012 weight=2;
    #server 172.17.16.147:8011 weight=2;
    }
    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            #root   html;
            #index  index.html index.htm;
        proxy_pass http://study_server/;
            proxy_cookie_path ~*^/.* /;
        proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }

Get session id: ViewBag.seId= HttpContext.Session.Id;

Startup.cs:

public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            //services.AddDistributedMemoryCache();

            services.AddDistributedRedisCache(options =>
            {
                options.Configuration = Configuration.GetConnectionString("RedisConnection");
                options.InstanceName = "master";
            });
            services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromSeconds(100);
                //options.Cookie.HttpOnly = true;
            });
            //services.AddSession();
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            //app.UseDeveloperExceptionPage();
            //app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseSession();
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }

Access URL: localhost and refresh again and again, the session id will be always changing.

I checked keys in redis server, it always generate the new key when refresh page. (e.g.masterdef69307-fbd3-c6ed-91d2-009b2306f902)

If I just use a server (localhost:8011):

upstream study_server{
        server localhost:8011 weight=1;
        #server localhost:8013 weight=1;
    #server localhost:8014 weight=1;
    #server 172.17.16.147:8012 weight=2;
    #server 172.17.16.147:8011 weight=2;
    }

The session id won’t be changed.

Anyone know it will be appreciated.

Thanks

5

Answers


  1. Chosen as BEST ANSWER

    Solved it by using

    var redis = ConnectionMultiplexer.Connect("<REDIS URI>");
    
    services.AddDataProtection().PersistKeysToRedis(redis, "DataProtection-Keys");
    

    Article:

    https://onecodex.ch/blogsdotnetcoredistributed-redis-cache/

    Necessary package: https://www.nuget.org/packages/Microsoft.AspNetCore.DataProtection.Redis/


  2. If the CheckConsentNeeded property is assigned with true, the application will not set any non-essential cookie without user consent. This includes the session cookie, which is non-essential by default.

    There are at least three solutions to your problem:

    1. You can set CheckConsentNeeded to false.
        ...
    
        options.CheckConsentNeeded = context => false;
    
        ...
    

    This will disable the whole cookie consent feature.

    1. You can mark the session cookie as essential.
        ...
    
        services.AddSession(options =>
        {
            options.IdleTimeout = TimeSpan.FromSeconds(100);
            options.Cookie.IsEssential = true;
        });
    
        ...
    

    This will allow the application to set the session cookie regardless of user’s consent.

    1. You can leave everything as it is now. In this case the session will start only after the user clicks the “Accept” button on the cookie use policy popup.
    Login or Signup to reply.
  3. I actually cannot reproduce the problem on a mac with the configuration (2 local servers load balanced via nginx and connected to the same local redis distributed cache)

    Anyways, if applicable, have you tried enabled ip_hash in nginx upstream module ?

    From the sessions persistance section in nginx doc:

    If there is the need to tie a client to a particular application server — in other words, make the client’s session “sticky” or “persistent” in terms of always trying to select a particular server — the ip-hash load balancing mechanism can be used.

    upstream study_server{
        ip_hash;
        server localhost:8011 weight=1;
        server localhost:8013 weight=1;
        #server localhost:8014 weight=1;
        #server 172.17.16.147:8012 weight=2;
        #server 172.17.16.147:8011 weight=2;
    }
    

    If that’s not solving your issue please have a look at similar issues on stack exchange:

    Login or Signup to reply.
  4. It seems that your sessions are not shared between your backends (servers).

    You must check where your cookies are saved, and if this “location” is shared between your multiple servers.

    If you use redis : Do they use the same redis ? the same namespace ?
    If it’s local storage on disk, do they shared the same directory, etc.

    Or as @Gomino said, your can use nginx sticky session to go to the same server each time (when your have a session). But this is not related to nginx configuration.

    Login or Signup to reply.
  5. According to this article. https://medium.com/@LuizAdolphs/asp-net-core-distributed-session-with-redis-8ce8bacf26cd

    The correct config Nginx is:

    worker_processes 1;
    
    events { worker_connections 1024; }
    
    http {
    
        sendfile on;
    
        upstream app_server {
            server app_1:5000;
            server app_2:5050;
        }
    
        server {
            listen 80;
    
            location / {
                proxy_pass         http://app_server;
                proxy_redirect     off;
                proxy_set_header   Host $host;
                proxy_set_header   X-Real-IP $remote_addr;
                proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header   X-Forwarded-Host $server_name;
            }
        }
    }
    

    Please take a look at X-Forwarded-Host. Try to use this if it not solve the problem, it can be a problem in Redis configuration.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search