多台服务器sessionId共享

news/2024/10/23 9:25:39/

目录

  • 多台服务器sessionId共享
    • 解决方案:
    • ASP.NET Core 参考代码(NET 7):
        • 登录处理
        • 登录(请求)过滤器
        • 过滤器使用
        • BaseController

多台服务器sessionId共享

session id是服务器首次与浏览器创建连接时,生成的id值,存入浏览器端cookie中,值加密的,下次请求时,浏览器自动带上session值发送给服务器,服务器根据cookie中存的session id值提取服务器存的用户信息,

基于上面的原理,在服务器集群中,如果服务器甲与浏览器建立了连接,则有个session id,如果下一个请求被负载均衡器转发给服务器乙处理,则服务器乙与浏览器也会建立一个新的session id,因为session的cookie名称相同,所以导致session id会被刷新,导致一直都没有登录,

解决方案:

登录成功后,将唯一凭据,比如【用户id+“#”+客户端ip+“#”+当前时间】,加密后的值作为cookie的值返回给浏览器,作为登录凭据,服务器根据此用户id作为缓存key,缓存值就存用户信息。
此时的cookie是可以在集群中传输的,服务器可以正常的提取到登录用户的id。

ASP.NET Core 参考代码(NET 7):

登录处理

/// <summary>///ajax, 登录处理/// </summary>/// <param name="account">账号</param>/// <param name="password">密码</param>/// <returns></returns>public async Task<IActionResult> LoginDo(string account, string password){//GetCustumerIP 获取当前客户端ipvar 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));}

登录(请求)过滤器

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");//删除cookiecontext.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();}//获取访问者ipreturn context.HttpContext.Connection.RemoteIpAddress.ToString();}}}

过滤器使用

public class HomeController :  BaseController 
{[LoginFilter]public ActionResult Index(){//当前登录用户var userLogin=CurrentLoginUser;return View();}}

BaseController

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();}//获取访问者ipreturn 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);}}}}
}

http://www.ppmy.cn/news/1114661.html

相关文章

【前端】jquery获取data-*的属性值

通过jquery获取下面data-id的值 <div id"getId" data-id"122" >获取id</div> 方法一&#xff1a;dataset()方法 //data-前缀属性可以在JS中通过dataset取值&#xff0c;更加方便 console.log(getId.dataset.id);//112//赋值 getId.dataset.…

扔掉你的开发板,跟我玩Mcore-全志h616

本文转载自WhyCan Forum(哇酷开发者社区)&#xff1a; https://whycan.com/t_10024.html 作者leefei 这是一个1.69寸触摸小电视。使用全志H616芯片&#xff0c;板上硬件有mpu6050陀螺仪&#xff0c;USB转ttl调试串口&#xff0c;一个USB接口&#xff0c;WIFI&蓝牙&#x…

【蓝桥杯选拔赛真题61】Scratch小猫照镜子 少儿编程scratch图形化编程 蓝桥杯选拔赛真题解析

目录 scratch小猫照镜子 一、题目要求 编程实现 二、案例分析 1、角色分析

9.19-21,openEuler与您相约2023欧洲开源峰会

2023年9月19日-21日&#xff0c;openEuler将参加在西班牙毕尔巴鄂举办的 OSSUMMIT 2023&#xff08;Open Source Summit Europe 2023&#xff09;&#xff0c;这是openEuler继去年正式亮相后的第二次全面参加该峰会。 Open Source Summit Europe是由Linux基金会主办&#xff0…

Python空值None的意义

在 Python 中&#xff0c;有一个特殊的常量 None&#xff08;N 必须大写&#xff09;。和 False 不同&#xff0c;它不表示 0&#xff0c;也不表示空字符串&#xff0c;而表示没有值&#xff0c;也就是空值。 这里的空值并不代表空对象&#xff0c;即 None 和 [] 以及 "&q…

ORB-SLAM3局部建图线程

一.总体流程 二.局部建图线程的目的和意义 1.承上启下&#xff0c;接受跟踪线程输入的关键帧并进行局部地图优化&#xff0c;删除冗余关键帧等&#xff0c;将优化后的关键帧发送给闭环线程。 2.实现中期数据关联 三.IMU初始化

20230915java面经记录

1.mq消息重复消费 rocketmq&#xff0c;kafka&#xff0c;rabbitmq等都保证at least one&#xff0c;至少一次&#xff0c;可能存在重复消费&#xff0c;要靠业务代码解决 原因&#xff1a;生产者发送重复消息or消费者消费重复消息 也就是说生产者在Broker响应时间后又发了一…

2023陇剑杯

2023陇剑杯初赛WP HW hard_web_1 ​ 首先判断哪个是服务器地址 ​ 从响应包看&#xff0c;给客户端返回数据包的就是服务器 所以确定服务器地址是192.168.162.188​ 再从开放端口来看&#xff0c;长期开放的端口 客户端发送一个TCP SYN包&#xff08;同步请求&#xff…