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()
     {
     }
 }
相关推荐
nothingbutluck46422 分钟前
2025.4.10 html有序、无序、定义列表、音视频标签
前端·html·音视频
爱上python的猴子1 小时前
chrome中的copy xpath 与copy full xpath的区别
前端·chrome
Lysun0012 小时前
dispaly: inline-flex 和 display: flex 的区别
前端·javascript·css
山禾女鬼0012 小时前
Vue 3 自定义指令
前端·javascript·vue.js
啊卡无敌2 小时前
Vue 3 reactive 和 ref 区别及 失去响应性问题
前端·javascript·vue.js
北桥苏2 小时前
Spine动画教程:皮肤制作
前端
涵信2 小时前
第九节:React HooksReact 18+新特性-React 19的use钩子如何简化异步操作?
前端·javascript·react.js
Aaaaaaaaaaayou2 小时前
浅玩一下 Mobile Use
前端·llm
这个昵称也不能用吗?2 小时前
react-native搭建开发环境过程记录
前端·react native·cocoapods
hy_花花2 小时前
Vue3.4之defineModel的用法
前端·vue.js