window.location.href 调用后存储在本地存储中的 JWT 令牌丢失

JWT token stored in localstorage lost after window.location.href call

我正在使用 Javascript Fetch API 来调用 Dot net web API。 使用 Visual Studio 代码 HTML/Javascript & Visual Studio 2019 用于 Dot Net Web API。 我正在尝试使用 Dot net C# Web API 实现登录功能,这将在响应中 return JWT 令牌并稍后使用该令牌调用单独的 Web API/Service(例如 EmployeeInfo )。

  1. 登录页面: 它显示用户 ID 和密码字段以及“登录”按钮
  2. 一旦用户点击登录按钮,函数 fnlogin 就会被调用
    function fnlogin() {
        const uname = document.getElementById('uname').value;
        const pwd = document.getElementById('pwd').value;

        const logindata = {
            username: uname,
            password: pwd
        }
        const loginurl = 'http://localhost:13402/api/Auth/Login';
        authenticate(loginurl, logindata);        
    }
        
    async function authenticate(loginurl, logindata) {
        console.log(logindata)
        const response = await fetch(loginurl , {
            method: "POST",
            mode: "cors",
            body: JSON.stringify(logindata),
            headers: { "Content-type" : "application/json, charset=UTF-8"}
        });
        const rdata = await response.json();
        console.log(rdata);
        if (!rdata.success) {
            document.getElementById("loginMessage").innerHTML = rdata.message;
            return;
        }

        const inMemoryToken = rdata.data
        localStorage.setItem('user', JSON.stringify(rdata));
        window.location.href = "http://localhost:5500/Employeeinfo1.html";

    }
  1. Web API returns JWT 令牌正确。

控制器中的代码如下:

        [HttpPost("Login")]
        public async Task<ActionResult<ServiceResponse<string>>> Login(UserLoginDto request)
        {
            var response = await _authRepo.Login(
                request.Username, request.Password
            );

            if (!response.Success)
            {
                return BadRequest(response);
            }

            return Ok(response);
        }

``
The code in AuthRepository class is as follows :
public class AuthRepository : IAuthRepository
{
    private readonly AppDbContext _context;
    private readonly IConfiguration _configuration;
    public AuthRepository(AppDbContext context, IConfiguration configuration)
    {
        _configuration = configuration;
        _context = context;

    }

    public async Task<ServiceResponse<string>> Login(string username, string password)
    {
        var response = new ServiceResponse<string>();
        var user = await _context.Users.FirstOrDefaultAsync(x => x.Username.ToLower().Equals(username.ToLower()));
        if (user == null)
        {
            response.Success = false;
            response.Message = "User not found.";
        }
        else if (!VerifyPasswordHash(password, user.PasswordHash, user.PasswordSalt))
        {
            response.Success = false;
            response.Message = "Wrong password.";
        }
        else
        {
            response.Data = CreateToken(user);
        }

        return response;
    }

    public async Task<ServiceResponse<User>> Register(User user, string password)
    {
        ServiceResponse<User> response = new ServiceResponse<User>();
        if (await UserExists(user.Username))
        {
            response.Success = false;
            response.Message = "User already exists.";
            return response;
        }

        CreatePasswordHash(password, out byte[] passwordHash, out byte[] passwordSalt);

        user.PasswordHash = passwordHash;
        user.PasswordSalt = passwordSalt;

        _context.Users.Add(user);
        await _context.SaveChangesAsync();
        response.Data = user;
        return response;
    }

    public async Task<bool> UserExists(string username)
    {
        if (await _context.Users.AnyAsync(x => x.Username.ToLower().Equals(username.ToLower())))
        {
            return true;
        }
        return false;
    }

    private void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
    {
        using (var hmac = new System.Security.Cryptography.HMACSHA512())
        {
            passwordSalt = hmac.Key;
            passwordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
        }
    }

    private bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
    {
        using (var hmac = new System.Security.Cryptography.HMACSHA512(passwordSalt))
        {
            var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
            for (int i = 0; i < computedHash.Length; i++)
            {
                if (computedHash[i] != passwordHash[i])
                {
                    return false;
                }
            }
            return true;
        }
    }

    private string CreateToken(User user)
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
            new Claim(ClaimTypes.Name, user.Username)
        };

        var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(_configuration.GetSection("AppSettings:Token").Value));

        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);

        var tokendDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(claims),
            Expires = System.DateTime.Now.AddDays(1),
            SigningCredentials = creds
        };

        var tokenHandler = new JwtSecurityTokenHandler();
        var token = tokenHandler.CreateToken(tokendDescriptor);

        return tokenHandler.WriteToken(token);
    }

4. Once the JWT token is returned , it is stored in LocalStorage. I verified in Chrome Dev Tools

But after the next screen is displayed, when I check in Chrome dev tools, the object/token is no longer present in the Local Storage.
Is this because of window.location.href will remove all local data in localStorage in the browser ?

I want to be able to use the token to pass to remaining html screens and web api 


您正在 http://127.0.0.1:5500 的本地存储中存储一个项目并试图从 http://localhost:5500 读取它。

来自 MDN Web 文档中的 Window.localStorage

The localStorage read-only property of the window interface allows you to access a Storage object for the Document's origin;

关于Origin

Web content's origin is defined by the scheme (protocol), host (domain), and port of the URL used to access it. Two objects have the same origin only when the scheme, host, and port all match.

如您所见,对于浏览器,来源不同,因为主机不匹配:127.0.0.1localhost 不同。

在任何地方使用 localhost127.0.0.1,但不要同时使用两者。