You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core 8中如何避免RefreshToken随每次请求自动发送?

解决RefreshToken随每次请求自动发送的安全问题

你的核心问题是RefreshToken的Cookie路径设置为"/",导致所有请求都会自动携带它,这确实存在安全风险——RefreshToken仅需在AccessToken过期时调用刷新接口使用,无需每次请求都暴露。以下是两种解决方案,优先推荐第一种:

方案一:限制RefreshToken Cookie的生效路径(推荐,安全性更高)

通过修改RefreshToken的Cookie Path 属性,仅让它在刷新AccessToken的专属接口路径下生效,这样只有调用刷新接口时才会携带RefreshToken,其他请求不会自动发送。

1. 修改Login接口的RefreshToken Cookie配置

将RefreshToken的Cookie路径改为你的刷新接口路径(假设刷新接口为 /Api/User/Auth/Refresh),同时纠正过期时间的错误(配置项是小时,应该用AddHours而非AddMinutes):

HttpContext.Response.Cookies.Append(
    "RefreshToken",
    result.RefreshToken,
    new CookieOptions
    {
        Expires = DateTime.Now.AddHours(
            int.Parse(_configuration["JWT:RefTknValidityInHours"])
        ),
        SameSite = SameSiteMode.Lax,
        HttpOnly = true,
        Path = "/Api/User/Auth/Refresh", // 仅在刷新接口路径下生效
        Domain = ".localhost",
    }
);

2. 调整JWT认证的消息接收逻辑

仅在处理刷新接口时,从Cookie中读取RefreshToken;其他正常请求读取AccessToken:

options.Events = new JwtBearerEvents
{
    OnMessageReceived = context =>
    {
        // 仅当请求刷新Token接口时,读取RefreshToken
        if (context.Request.Path.StartsWithSegments("/Api/User/Auth/Refresh"))
        {
            context.Token = context.Request.Cookies["RefreshToken"];
        }
        else
        {
            // 普通业务请求读取AccessToken
            context.Token = context.Request.Cookies["AccessToken"];
        }
        return Task.CompletedTask;
    }
};

这种方案的优势是保持RefreshToken在HttpOnly Cookie中,能有效防范XSS攻击窃取Token,安全性远高于前端存储方案。

方案二:前端存储RefreshToken并手动按需发送(不推荐,存在XSS风险)

如果因业务特殊需求必须由前端控制RefreshToken的发送时机,可以将RefreshToken返回给前端,存入localStorage,在需要刷新AccessToken时手动携带。但此方案下RefreshToken容易被XSS攻击窃取,需谨慎使用。

1. 修改Login接口返回RefreshToken

将Login接口的请求方法从HEAD改为POST(HEAD请求无响应体),并返回RefreshToken:

[HttpPost("Auth/Login")]
public async Task<IResult> Login([FromHeader] long phoneNumber)
{
    AuthTokenDTO result = await _dBContext.User.Login(phoneNumber);
    if (result is null)
        return Results.BadRequest();

    // 仅设置AccessToken为Cookie
    HttpContext.Response.Cookies.Append(
        "AccessToken",
        result.Token,
        new CookieOptions
        {
            Expires = DateTime.Now.AddMinutes(
                int.Parse(_configuration["JWT:TknValidityInMunutes"])
            ),
            SameSite = SameSiteMode.Lax,
            HttpOnly = true,
            Path = "/",
            Domain = ".localhost",
        }
    );

    // 将RefreshToken作为响应体返回给前端
    return Results.Ok(new { RefreshToken = result.RefreshToken });
}

2. 前端存储并手动发送RefreshToken

登录时将RefreshToken存入localStorage,刷新AccessToken时手动携带:

// 登录请求
const loginResponse = await fetch('http://localhost:5247/Api/User/Auth/Login', {
    method: 'POST',
    credentials: 'include',
    headers: { phoneNumber, 'Content-Type': 'application/json' }
});
const loginData = await loginResponse.json();
localStorage.setItem('refreshToken', loginData.RefreshToken);

// 刷新AccessToken请求
const refreshToken = localStorage.getItem('refreshToken');
const refreshResponse = await fetch('http://localhost:5247/Api/User/Auth/Refresh', {
    method: 'POST',
    credentials: 'include',
    headers: { 
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${refreshToken}`
    }
});

3. 后端刷新接口读取RefreshToken

在刷新接口中,从请求头的Authorization字段读取RefreshToken进行验证。


内容的提问来源于stack exchange,提问作者Reza245

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 01:56:01