Partage d'ID de session sur plusieurs serveurs

Partage d'ID de session sur plusieurs serveurs

L'identifiant de session est la valeur d'identifiant générée lorsque le serveur établit une connexion avec le navigateur pour la première fois. Il est stocké dans le cookie côté navigateur et la valeur est cryptée. La prochaine fois que la demande est effectuée, le navigateur apporte automatiquement l'identifiant de session. valeur de session et l'envoie au serveur. Le serveur la stocke dans le cookie en fonction de la valeur stockée dans le cookie. La valeur de l'identifiant de session extrait les informations utilisateur stockées dans le serveur.

Sur la base du principe ci-dessus, dans le cluster de serveurs, si le serveur A établit une connexion avec le navigateur, il y aura un identifiant de session. Si la prochaine requête est transmise au serveur B par l'équilibreur de charge, le serveur B et le navigateur établiront également un identifiant de session. Nouvel identifiant de session, car le nom du cookie de la session est le même, donc l'identifiant de session sera actualisé, ce qui n'entraînera aucune connexion.

solution:

Après une connexion réussie, les informations d'identification uniques, telles que [ID utilisateur+"#"+adresse IP du client+"#"+heure actuelle], la valeur cryptée est renvoyée au navigateur en tant que valeur de cookie, en tant qu'informations d'identification de connexion, et le serveur l'utilise. L'identifiant utilisateur en tant que clé de cache et valeur de cache stockent les informations utilisateur.
À ce stade, le cookie peut être transmis dans le cluster et le serveur peut normalement extraire l'ID de l'utilisateur connecté.

Code de référence ASP.NET Core (NET 7) :

Traitement de connexion

        /// <summary>
        ///ajax, 登录处理
        /// </summary>
        /// <param name="account">账号</param>
        /// <param name="password">密码</param>
        /// <returns></returns>
        public async Task<IActionResult> LoginDo(string account, string password)
        {
    
    
		    //GetCustumerIP 获取当前客户端ip
            var result = await userBLL.DoLoginAsync(account, password, null, GetCustumerIP);          
            if (result.Code == 200)
            {
    
    
                
                var _cookieOptions = new CookieOptions()
                {
    
    
                    //Expires = DateTime.Now.AddMinutes(30),
                    HttpOnly = true, /* 防御XSS攻击  */
                };

                //将用户id存入cookie 
                //解决nginx反向代理cookie问题;
                string loginAuthTxt = result.Data.Authorize_user_id.ToString() + "#" + GetCustumerIP + "#" + DateTime.Now.AddHours(12).ToString("yyyy-MM-dd HH:mm:ss.fff");
                
				//AES加密
				string encryUserId = AesHelpter.AESEncryptToHex(loginAuthTxt);
                Response.Cookies.Append(CacheKeyConfig.CookieName_loginAuth, encryUserId, _cookieOptions);
 
            }
            return Json(new Model.Result(  result.Msg, result.Code));
        }

Filtre de connexion (demande)
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;

using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Policy;

using Microsoft.AspNetCore.Routing;
using Web_rongmeiti_sys.Handler;
using Web_rongmeiti_sys.Model;
using Newtonsoft.Json.Linq;
using Microsoft.JSInterop.Infrastructure;

namespace Web_rongmeiti_sys
{
    
    
    /*
IAsyncAuthorizationFilter
IAuthorizationFilter 
 AuthorizeAttribute 
    */

    /// <summary>
    /// 登录验证,权限验证,action过滤。FunId为空只验证登录,不验证权限
    /// </summary>
    public class LoginFilter : Attribute, IAsyncAuthorizationFilter
    {
    
    
        public LoginFilter()
        {
    
    
        }

        public LoginFilter(string funId)
        {
    
    
            FunId = funId;
        }

        /// <summary>
        /// 方法标识id
        /// </summary>
        private string FunId {
    
     get; set; }

        public Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
    
    
 
            获取登录用户id值,修改时间:2023-8-2 09:37:10 
            string? userId_encry = string.Empty;
            context.HttpContext.Request.Cookies.TryGetValue(CacheKeyConfig.CookieName_loginAuth, out userId_encry);
    
            bool isAjax = MyExceptionFilter.IsAjax(context.HttpContext.Request);
            if (string.IsNullOrWhiteSpace(userId_encry))
            {
    
    
               
                //没有登录,去登录
                goto To_login;
            }

            //验证cookie值是否有效?
            try
            {
    
    
                string descValue = AesHelpter.AESDecryptByHex(userId_encry);
                if (descValue.IndexOf("#") == -1)
                {
    
    
                    goto To_login;
                }
                string tokenIP = descValue.Split("#")[1];
                if (!tokenIP.Equals(GetCustumerIP(context)))
                {
    
    
                    goto To_login;
                }
                string expireTimeStr = descValue.Split("#")[2];
                if (!DateTime.TryParse(expireTimeStr, out DateTime expireTime) ||
                    expireTime <= DateTime.Now)
                {
    
    
                    goto To_login;
                }
            }
            catch (Exception)
            {
    
    
                goto To_login;
            }
                   
            if (string.IsNullOrWhiteSpace(FunId))
            {
    
    
                return Task.CompletedTask;
            }
 
        To_login:
            if (isAjax)
            {
    
    
                //无权访问
                //context.Result = new UnauthorizedResult();
                context.Result = new JsonResult(new {
    
     Code = 500, Msg = "登录失效,请重新登录" })
                {
    
    
                    StatusCode = StatusCodes.Status401Unauthorized
                };
                return Task.CompletedTask;
            }
            //没有登录,去登录
            context.Result = new RedirectResult("/user/Login");

            //删除cookie
            context.HttpContext.Response.Cookies.Delete(CacheKeyConfig.CookieName_loginAuth);
            return Task.CompletedTask;
        }

        /// <summary>
        ///  获取访问者ip
        /// </summary>
        public string GetCustumerIP(AuthorizationFilterContext context)
        {
    
    
            var request = context.HttpContext.Request;
            Microsoft.Extensions.Primitives.StringValues ip;

            //X-Real-IP,nginx代理传输的客户端真实ip,添加时间:2023-8-2 09:42:03 
            if (request.Headers.TryGetValue("X-Real-IP", out ip))
            {
    
    
                return ip.ToString();
            }

            //获取访问者ip
            return context.HttpContext.Connection.RemoteIpAddress.ToString();

        }



    }

}
Utilisation du filtre
public class HomeController :  BaseController 
{
    
    

      [LoginFilter]
      public ActionResult Index()
      {
    
    
      	  //当前登录用户
      	  var userLogin=CurrentLoginUser;
          return View();
      }
 }
Contrôleur de base
using Microsoft.AspNetCore.Mvc;
using Web_rongmeiti_sys.Business_Interface;
using Web_rongmeiti_sys.DAL_Interface;
using Web_rongmeiti_sys.Model;

namespace Web_rongmeiti_sys.Controllers
{
    
    
    /// <summary>
    /// 基础,控制器,
    /// </summary>
    /// 创建时间:2023-6-26 15:44:17 
    public class BaseController : Controller
    {
    
    
        /// <summary>
        ///  获取访问者ip
        /// </summary>
        public string GetCustumerIP
        {
    
    
            get
            {
    
    
                Microsoft.Extensions.Primitives.StringValues ip;

                //X-Real-IP,nginx代理传输的客户端真实ip,添加时间:2023-8-2 09:42:03 
                if (Request.Headers.TryGetValue("X-Real-IP", out ip))
                {
    
    
                    return ip.ToString();
                }

                //获取访问者ip
                return HttpContext.Connection.RemoteIpAddress.ToString();
            }
        }

        /// <summary>
        /// 当前登录用户
        /// </summary>
        public Authorize_user CurrentLoginUser
        {
    
    
            get
            {
    
    
                try
                {
    
    
                    获取登录用户id值, 2023-8-2 09:42:53 
                    string? userId_encry = string.Empty;
                    Request.Cookies.TryGetValue(CacheKeyConfig.CookieName_loginAuth, out userId_encry);
                    if (string.IsNullOrEmpty(userId_encry))
                    {
    
    
                        throw new Exception("登录失效,userId_encry ");
                    }
                    string desc = AesHelpter.AESDecryptByHex(userId_encry);
                    string userId = desc.Split("#")[0];

             
                    Authorize_user? user = System.Runtime.Caching.MemoryCache.Default.Get(userId) as Authorize_user;
                    if (user == null)
                    {
    
    
                        IUserBusiness userBusiness = ServicesHelpter.GetService<IUserBusiness>();
                        long userId2 = long.Parse(userId);
                        user = userBusiness.GetAsync(userId2).Result;

                        //登录成功,缓存用户,缓存12小时
                        System.Runtime.Caching.MemoryCache.Default.Set(userId, user, DateTimeOffset.Now.AddSeconds(43200));
                    }

                    return user;
                }
                catch (Exception ex)
                {
    
    
                    throw new Exception("获取登录用户异常,", ex);
                }
            }
        }

    }
}

おすすめ

転載: blog.csdn.net/u011511086/article/details/132987435