ASP.NET Web的 Razor Pages应用,ajax调用记录以及Cookie配置

1、环境说明

.net sdk6.0

vs2022

2、Program.cs配置

一是配置AddAntiforgery自定义的HeaderName,因为这是.net corede的默认的预防跨网站请求伪造 (XSRF/CSRF) 攻击的手段,关闭了也不太好,所以添加自定义的头。

二是Cookie认证的配置,如果不喜欢用Cookie,可以自己改成jwt之类的。

复制代码
builder.Services.AddAntiforgery(o => o.HeaderName = "RequestVerificationToken");

#region Cookie认证配置
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies"; // 默认使用Cookie认证
    options.DefaultChallengeScheme = "Cookies"; // 默认的质询方案(未登录时使用的方案)
})
.AddCookie("Cookies", options =>
{
    options.LoginPath = "/User/UserLogin"; // 登录页面路径
    options.AccessDeniedPath = "/User/AccessDenied"; // 拒绝访问页面路径
    options.ExpireTimeSpan = TimeSpan.FromHours(2); // Cookie过期时间
    options.SlidingExpiration = true; // 滑动过期
});
#endregion

3、UserLogin.cshtml

下面是页面部分代码,核心在于@Html.AntiForgeryToken()。

以及ajax请求的部分:重要的一是url,而是header的部分。

url不能错,网页的命名空间也不能错,错了就会返回html。

复制代码
@page
@model chocolate_web.Pages.User.UserLoginModel
@{
    ViewData["Title"] = "用户登录";
}
@Html.AntiForgeryToken()


@section Scripts
{
    <script type="text/javascript">
        // 初始化 Toast
        const toastEl = document.querySelector('.toast');
        const toast = new bootstrap.Toast(toastEl);

        $(document).ready(function () {
            $('#registrationButton').click(function(){

                if($('#username').val() === "")
                {
                    $('.toast-body').html("请输入账号!"),
                    toast.show();
                    return;
                }
                if($('#password').val() === "")
                {
                    $('.toast-body').html("请输入密码!"),
                    toast.show();
                    return;
                }

                // 获取表单数据
                var formData = {
                    account: $('#username').val(),
                    password: $('#password').val(),
                    rememberMe: false,//$('#remember_me').is(':checked')
                };

                // 禁用提交按钮
                $('#registrationButton').prop('disabled', true);
                $('#registrationButton').text('登录中...');

                // 发送登录请求
                $.ajax({
                    url: '?handler=Login',
                    type: 'POST',
                    contentType: 'application/json',
                    data: JSON.stringify(formData),
                    headers: {
                        "RequestVerificationToken": $('input[name="__RequestVerificationToken"]').val()
                    },
                    success: function (response) {
                        if (response.success) {
                            // 登录成功
                            window.location.href = response.returnUrl; // 重定向
                        } else {
                            $('.toast-body').html(response.message),
                            toast.show();
                            $('#registrationButton').prop('disabled', false);
                            $('#registrationButton').text('登录');
                        }
                    },
                    error: function (xhr) {
                        //toast.show();
                        //alert('登录失败,请稍后重试');
                    },
                    complete: function () {
                        // 恢复提交按钮
                        $('#registrationButton').prop('disabled', false);
                        $('#registrationButton').text('登录');
                    }
                });
            });
        });
    </script>
}

4、UserLogin.cshtml.cs

复制代码
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Security.Claims;
using Core_Database.EFCodeFirstDAL;
using Core_Database.InModel;
using Core_Database.Utils;

namespace chocolate_web.Pages.User
{
    /// <summary>
    /// 用户登录页面
    /// </summary>
    public class UserLoginModel : PageModel
    {

        public void OnGet(string ReturnUrl = null)
        {
            TempData["ReturnUrl"] = ReturnUrl;
            // 如果用户已经登录,重定向到首页
            if (User.Identity.IsAuthenticated)
            {
                Response.Redirect(ReturnUrl==null ? "/User/UserCenter" : ReturnUrl);
            }
        }

        public async Task<IActionResult> OnPostLoginAsync([FromBody] UserLogModel model)
        {
            var ReturnUrl = TempData["ReturnUrl"];
            if (ModelState.IsValid)
            {
                try
                {
                    // 验证用户名和密码
                    这里自定义的方法

                    string token = UtilsTools.CalculateMD5(UtilsTools.CalculateMD5(model.password) + user.salt);
                    if (!user.password.Equals(token))
                    {
                        return new JsonResult(new { success = false, message = "用户名或密码错误" });
                    }

                    // 创建身份声明
                    var claims = new List<Claim>
                    {
                        new Claim(ClaimTypes.Name, user.account),
                        new Claim(ClaimTypes.NameIdentifier, user.id.ToString()),
                        // 可以根据需要添加更多声明,比如角色等
                        new Claim("TrueName", user.truename ?? string.Empty)
                    };

                    var claimsIdentity = new ClaimsIdentity(claims, "Cookies");
                    var authProperties = new AuthenticationProperties
                    {
                        IsPersistent = model.rememberMe, // 是否记住登录状态
                        ExpiresUtc = model.rememberMe ? DateTimeOffset.UtcNow.AddDays(7) : DateTimeOffset.UtcNow.AddHours(2)
                    };

                    await HttpContext.SignInAsync("Cookies", new ClaimsPrincipal(claimsIdentity), authProperties);

                    //if(ReturnUrl != null && Url.IsLocalUrl(ReturnUrl.ToString()))
                    //{
                    //    return RedirectToPage(ReturnUrl.ToString());
                    //} 
                    //else
                    //{
                    //    return RedirectToPage("/User/UserCenter");
                    //}

                    //返回登录成功信息和重定向URL
                    return new JsonResult(new
                    {
                        success = true,
                        message = "登录成功",
                        returnUrl = (ReturnUrl != null && Url.IsLocalUrl(ReturnUrl.ToString())) ? ReturnUrl.ToString() : "/User/UserCenter"
                    });
                }
                catch (Exception ex)
                {
                    return new JsonResult(new { success = false, message = "登录失败:" + ex.Message });
                }
            }
            else
            {
                return new JsonResult(new { success = false, message = "登录失败"});
            }
        }

        /// <summary>
        /// 退出登录
        /// </summary>
        /// <returns></returns>
        public async Task<IActionResult> OnPostLogoutAsync()
        {
            await HttpContext.SignOutAsync("Cookies");
            return new JsonResult(new { success = true, message = "已退出登录" });
        }
    }
}

5、没有登录不允许访问的页面

复制代码
 [Authorize]
 public class UserCenterModel : PageModel
 {
     public void OnGet()
     {
     }
 }
相关推荐
zhanshuo8 分钟前
不依赖框架,如何用 JS 实现一个完整的前端路由系统
前端·javascript·html
火柴盒zhang9 分钟前
websheet在线电子表格(spreadsheet)在集团型企业财务报表中的应用
前端·html·报表·合并·spreadsheet·websheet·集团财务
khalil11 分钟前
基于 Vue3实现一款简历生成工具
前端·vue.js
拾光拾趣录18 分钟前
浏览器对队头阻塞问题的深度优化策略
前端·浏览器
用户81221993672218 分钟前
[已完结]后端开发必备高阶技能--自研企业级网关组件(Netty+Nacos+Disruptor)
前端
万少23 分钟前
2025中了 聊一聊程序员为什么都要做自己的产品
前端·harmonyos
abigale032 小时前
webpack+vite前端构建工具 -11实战中的配置技巧
前端·webpack·node.js
专注API从业者3 小时前
构建淘宝评论监控系统:API 接口开发与实时数据采集教程
大数据·前端·数据库·oracle
Joker`s smile3 小时前
Chrome安装老版本、不同版本,自制便携版本用于前端调试
前端·chrome
weixin_416639973 小时前
爬虫工程师Chrome开发者工具简单介绍
前端·chrome·爬虫