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()
     {
     }
 }
相关推荐
uhakadotcom1 小时前
刚刚发布的React 19.1提供了什么新能力?
前端·javascript·面试
uhakadotcom1 小时前
Expo 简介:跨平台移动应用开发的强大工具
前端·javascript·面试
markzzw1 小时前
浏览器插件钱包(一) - 区块链世界的入口
前端·web3·区块链
夕水1 小时前
终于,我也能够写出一款代码编辑器
前端
red润2 小时前
npm包autocannon牛逼的后台压力测试库
前端·javascript·node.js
黄蘑菇2 小时前
white-space、word-break、overflow-wrap(原名word-wrap)的区别
前端
渔樵江渚上2 小时前
JavaScript函数柯里化:优雅的函数式编程实践
前端·javascript·面试
the_one2 小时前
如何判断一个属性是否存在
前端·javascript·面试
张开心_kx2 小时前
5202年了,还不懂原型链吗?
前端
用户613346716532 小时前
开发体育赛事直播系统:炫彩弹幕直播间界面技术实现方案
前端·后端