C#、ASP.NET 环境下如何在 form 身份验证User.Identity中携带像 UserID 这样的信息

本文详细介绍了如何在ASP.NET中自定义身份验证Cookie,以存储除用户名和认证票据外的其他数据,如数据库中的UserID。通过自定义Cookie,开发者能够灵活地在用户会话中存储更多个性化信息。

ASP.NET 自己带了一个可以自动存储 form 身份验证信息的类 FormsAuthentication ,但这个 FormsAuthentication 自动的 Cookie 除了包含用户名和认证票据以外,不能自己带其它的数据,如数据库中的 UserID(ASP.NET 的登陆控件使用的数据库中是 uniqueidentifier 类型的)。

我们可以通过自定义 ASP.NET 控件使用的身份验证 Cookie 的方法来解决这个问题。

当通过身份验证后,一般是通过下面的语句来保存身份验证 Cookie 并把页面转向到默认页面。

             FormsAuthentication.RedirectFromLoginPage(UserName.Text, false);

因为我们自定义了身份验证 Cookie , 因此,不再使用这个语句,而是直接使用转向语句,程序如下:

            //这里省略了从数据库中读取 UserID 的语句

            string userID = row["userid"].ToString();

            //定义身份验证 Cookie
            FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, UserName.Text, DateTime.Now, DateTime.Now.AddDays(365), true, userID);

            //加密身份验证 Cookie
            string enTicket = FormsAuthentication.Encrypt(ticket);

            //存储身份验证 Cookie,这里很重要,因为 ASP.NET 的默认身份验证 Cookie 的名字是“.ASPXAUTH”

    //所以这里一定要使用这个名字,这个默认的名字可以在 ASP.NET 配置程序里修改

            HttpContext.Current.Response.Cookies.Add(new HttpCookie(".ASPXAUTH", enTicket));
            db.Close();
            //由于自定义了 ASP.NET 用于身份验证的 Cooike ,因此不使用 ASP.NET 的存储身份验证 Cookie 并跳转的语句
            //FormsAuthentication.RedirectFromLoginPage(UserName.Text, false);
            //而使用自定义跳转语句
            Response.Redirect(@"/login/my.aspx");

这样在其他程序中如果需要读取 UserID 的时候,只需要下面的程序即可:

    //从 Page 的属性中读取身份验证信息,并强制转换成 FormsIdentity 类型

    FormsIdentity identity = (FormsIdentity)Page.User.Identity;

    //读取其中的 Ticket.UserData

            FormsAuthenticationTicket ticket = identity.Ticket;
            string userData = ticket.UserData;
            Response.Write(User.Identity.Name + ":" + userData);

 

当然,由于 UserData 是 string 类型的,因此可以存储用户需要的任何信息,但这个信息不要过长,否则可能会超出浏览器所允许的 Cookie 的最大长度,造成错误

<think>我们正在寻找一个使用ASP.NET开发的图书馆座位预约管理系统的代码示例或实现方案。由于系统较为复杂,我们不可能提供完整源代码,但可以给出一个核心功能的实现框架和代码示例,包括:1.数据库设计(核心表)2.预约功能的后端逻辑(C#)3.座位选择和预约的前端示例(ASP.NETWebForms或MVCRazor视图)###核心数据库设计假设系统需要以下表:-**Seats**:存储座位信息-`SeatID`(主键)-`Location`(位置描述)-`SeatNumber`(座位号)-`IsAvailable`(是否可用,可能还有更复杂的状态如预留、使用中)-**Reservations**:存储预约记录-`ReservationID`(主键)-`UserID`(外键,关联用户)-`SeatID`(外键,关联座位)-`StartTime`(预约开始时间)-`EndTime`(预约结束时间)-`Status`(状态,如已预约、使用中、已完成、取消)###后端预约逻辑(C#示例)在ASP.NET中,我们可能会创建一个服务类来处理预约逻辑,例如:```csharppublicclassReservationService{privatereadonlyApplicationDbContext_context;publicReservationService(ApplicationDbContextcontext){_context=context;}//预约座位publicasyncTask<ReservationResult>ReserveSeatAsync(intseatId,stringuserId,DateTimestartTime,DateTimeendTime){//检查座位是否存在且可用varseat=await_context.Seats.FindAsync(seatId);if(seat==null)returnReservationResult.Fail("座位不存在");if(!seat.IsAvailable)returnReservationResult.Fail("座位当前不可用");//检查该时间段内座位是否被预约(冲突检测)boolhasConflict=await_context.Reservations.AnyAsync(r=>r.SeatID==seatId&&(startTime< r.EndTime&&endTime>r.StartTime)&&r.Status!=ReservationStatus.Cancelled&&r.Status!=ReservationStatus.Completed);if(hasConflict)returnReservationResult.Fail("该时间段内座位已被预约");varreservation=newReservation{UserID=userId,SeatID=seatId,StartTime=startTime,EndTime=endTime,Status=ReservationStatus.Reserved};_context.Reservations.Add(reservation);await_context.SaveChangesAsync();returnReservationResult.Success(reservation.ReservationID);}}publicenumReservationStatus{Reserved,InUse,Completed,Cancelled}publicclassReservationResult{publicboolSuccess{get;}publicstringMessage{get;}publicint?ReservationId{get;}privateReservationResult(boolsuccess,stringmessage,int?reservationId){Success=success;Message=message;ReservationId=reservationId;}publicstaticReservationResultSuccess(intreservationId)=>newReservationResult(true,null,reservationId);publicstaticReservationResultFail(stringmessage)=>newReservationResult(false,message,null);}```###前端座位选择和预约(ASP.NETMVCRazor视图示例)假设我们有一个页面显示图书馆的座位分布,并允许用户选择日期和时间段进行预约。```html@modelLibrarySeatReservation.Models.SeatSelectionModel<h2>选择座位</h2><divclass="calendar"><!--日期选择器--><inputtype="date"id="reservationDate"/></div><divclass="time-slot"><label>开始时间:</label><inputtype="time"id="startTime"/><label>结束时间:</label><inputtype="time"id="endTime"/></div><divclass="seat-map"><!--座位图,可能是一个表格或SVG,这里用一个简单的div代表座位-->@foreach(varseatinModel.AvailableSeats){<divclass="seatavailable"data-seat-id="@seat.SeatID">座位@seat.SeatNumber</div>}</div><buttonid="reserveButton">预约</button>@sectionscripts{<script>$(function(){varselectedSeatId=null;$('.seat').click(function(){$('.seat').removeClass('selected');$(this).addClass('selected');selectedSeatId=$(this).data('seat-id');});$('#reserveButton').click(function(){vardate=$('#reservationDate').val();varstartTime=$('#startTime').val();varendTime=$('#endTime').val();if(!selectedSeatId||!date||!startTime||!endTime){alert('请选择座位并填写完整的预约时间');return;}varstartDateTime=date+'T'+startTime;varendDateTime=date+'T'+endTime;//发送预约请求$.post('/Reservation/Reserve',{seatId:selectedSeatId,startTime:startDateTime,endTime:endDateTime},function(data){if(data.success){alert('预约成功,预约号:'+data.reservationId);}else{alert('预约失败:'+data.message);}});});});</script>}```###其他注意事项1.**用户认证**:预约系统需要用户登录,我们可以使用ASP.NETIdentity。2.**预约规则**:可能需要限制预约时长(例如最多4小时)和提前预约的时间(例如只能预约未来一周的座位)。3.**签到机制**:用户可能需要在预约时间开始后的一段时间内到现场签到(例如通过扫描座位上的二维码),否则预约会被取消。###开源项目参考GitHub上可能有类似的开源项目,可以搜索关键词如“LibrarySeatReservationASP.NET”。注意检查项目的许可协议。§§相关问题§§1.何在ASP.NETCore中实现图书馆座位预约系统的用户认证?2.如何设计图书馆座位预约系统的数据库以支持多个图书馆和楼层?3.图书馆座位预约系统如何实现签到功能以防止预约滥用?4.ASP.NET中如何实现预约到期自动释放座位的功能?</think> 下面我将提供一个基于ASP.NET的图书馆座位预约管理系统的实现方案和核心代码示例。该方案采用分层架构,包含数据库设计、业务逻辑和前端界面实现。 ### 系统架构设计 ``` 表现层 (ASP.NET MVC) ↓ 业务逻辑层 (C# Services) ↓ 数据访问层 (Entity Framework) ↓ 数据库 (SQL Server) ``` ### 核心数据库表设计 ```sql CREATE TABLE Seats ( SeatID INT PRIMARY KEY IDENTITY, Location NVARCHAR(50) NOT NULL, -- 区域位置 Number NVARCHAR(10) NOT NULL, -- 座位编号 Type NVARCHAR(20), -- 座位类型 IsAvailable BIT DEFAULT 1 -- 是否可用 ); CREATE TABLE Users ( UserID INT PRIMARY KEY IDENTITY, StudentID NVARCHAR(20) UNIQUE, -- 学号/工号 Name NVARCHAR(50) NOT NULL, Password NVARCHAR(100) NOT NULL -- 加密存储 ); CREATE TABLE Reservations ( ReservationID INT PRIMARY KEY IDENTITY, UserID INT FOREIGN KEY REFERENCES Users(UserID), SeatID INT FOREIGN KEY REFERENCES Seats(SeatID), StartTime DATETIME NOT NULL, EndTime DATETIME NOT NULL, Status NVARCHAR(20) DEFAULT 'Reserved' -- Reserved, InUse, Completed ); ``` ### 核心功能代码示例 #### 1. 座位预约服务(业务逻辑层) ```csharp public class ReservationService { private readonly AppDbContext _context; public ReservationService(AppDbContext context) { _context = context; } public ReservationResult ReserveSeat(int userId, int seatId, DateTime start, DateTime end) { // 检查座位可用性 var isAvailable = !_context.Reservations.Any(r => r.SeatID == seatId && r.Status != "Completed" && ((start >= r.StartTime && start < r.EndTime) || (end > r.StartTime && end <= r.EndTime) || (start <= r.StartTime && end >= r.EndTime))); if (!isAvailable) return ReservationResult.Failed("该时间段座位已被预约"); // 创建新预约 var reservation = new Reservation { UserID = userId, SeatID = seatId, StartTime = start, EndTime = end, Status = "Reserved" }; _context.Reservations.Add(reservation); _context.SaveChanges(); return ReservationResult.Success(reservation); } public void CheckIn(int reservationId) { var reservation = _context.Reservations.Find(reservationId); if (reservation != null && reservation.Status == "Reserved") { reservation.Status = "InUse"; _context.SaveChanges(); } } } ``` #### 2. 预约控制器(MVC 表现层) ```csharp public class ReservationController : Controller { private readonly ReservationService _reservationService; public ReservationController(ReservationService reservationService) { _reservationService = reservationService; } [HttpPost] public ActionResult Create(ReservationModel model) { var result = _reservationService.ReserveSeat( User.Identity.GetUserId(), model.SeatId, model.StartTime, model.EndTime); if (result.Success) return RedirectToAction("Details", new { id = result.Reservation.ReservationID }); ViewBag.Error = result.Message; return View(model); } [HttpPost] public ActionResult CheckIn(int id) { _reservationService.CheckIn(id); return RedirectToAction("Index"); } } ``` #### 3. 座位状态展示视图(Razor) ```html @model IEnumerable<Seat> <div class="seat-map"> @foreach (var seat in Model) { <div class="seat @(seat.IsAvailable ? "available" : "occupied")" data-id="@seat.SeatID"> <span>@seat.Number</span> <span class="badge">@seat.Type</span> </div> } </div> <!-- 预约模态框 --> <div class="modal fade" id="reservationModal"> @using (Html.BeginForm("Create", "Reservation")) { <input type="hidden" name="SeatId" id="selectedSeat" /> <div class="form-group"> <label>开始时间</label> <input type="datetime-local" name="StartTime" class="form-control" /> </div> <div class="form-group"> <label>结束时间</label> <input type="datetime-local" name="EndTime" class="form-control" /> </div> <button type="submit" class="btn btn-primary">确认预约</button> } </div> ``` ### 关键功能实现细节 1. **座位状态实时更新**:使用SignalR实现座位状态实时推送 2. **预约冲突检测**:时间重叠检测算法(使用SQL窗口函数或内存计算) 3. **自动释放机制**:后台任务定时检查超时未签到预约 ```csharp // 在Program.cs中注册后台服务 builder.Services.AddHostedService<ReservationCleanupService>(); ``` ### 相关开源项目参考 1. [Library-Seat-Management-System (GitHub)](https://github.com/orgs/Library-Seat-Management-System) - 使用ASP.NET Core实现的完整系统 2. [SeatReservationApp (GitHub)](https://github.com/SeatReservationApp) - 包含移动端集成的方案 > 提示:实际开发时应考虑添加更多功能如: > - 座位分区管理 > - 预约历史查询 > - 信用积分系统 > - 管理员审批流程 > - 移动端适配(可结合MAUI或PWA)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值