如果我想让我的 Spring/React 应用程序在打开新标签页时记住我的登录信息,我需要从哪里开始?

Where do i need to start if I want my Spring/React app to remember my login info when opening a new tab?

我有一个使用 JWT 保护的网络应用程序。如果我打开一个新标签页,如何让它记住我的登录数据而不是再次输入?我使用 axios.post 来验证端点并将令牌保存在 localStorage 中 我的前端认证服务代码:

import axios from 'axios'

const API_URL = 'http://localhost:8080/map-runner'

export const USER_NAME_SESSION_ATTRIBUTE_NAME = 'authenticatedUser'

class AuthenticationService {

    executeJwtAuthenticationService(username, password) {
        return axios.post(`${API_URL}/authenticate`, {
            username,
            password
        })
    }

    registerSuccessfulLoginForJwt(username, token) {
        sessionStorage.setItem(USER_NAME_SESSION_ATTRIBUTE_NAME, username)
        localStorage.setItem("token", token)
    }

    createJWTToken(token) {
        return 'Bearer ' + token
    }


    logout() {
        sessionStorage.removeItem(USER_NAME_SESSION_ATTRIBUTE_NAME);
    }

    isUserLoggedIn() {
        let user = sessionStorage.getItem(USER_NAME_SESSION_ATTRIBUTE_NAME)
        if (user === null) return false
        return true
    }

    getLoggedInUserName() {
        let user = sessionStorage.getItem(USER_NAME_SESSION_ATTRIBUTE_NAME)
        if (user === null) return ''
        return user
    }

    setupAxiosInterceptors(token) {
        axios.interceptors.request.use(
            (config) => {
                if (this.isUserLoggedIn()) {
                    config.headers.authorization = token
                }
                return config
            }
        )
    }
}

export default new AuthenticationService()

现在我的登录组件:

import React, { Component } from 'react'
import AuthenticationService from '../service/AuthenticationService';

class LoginComponent extends Component {

    constructor(props) {
        super(props)

        this.state = {
            username: '',
            password: '',
            hasLoginFailed: false,
            showSuccessMessage: false
        }
    }

    handleChange = (event) => {
        this.setState(
            {
                [event.target.name]
                    : event.target.value
            }
        )
    }

    loginClicked = () => {
        AuthenticationService
            .executeJwtAuthenticationService(this.state.username, this.state.password)
            .then((response) => {
                AuthenticationService.registerSuccessfulLoginForJwt(this.state.username, response.data.token)
                console.log(response.data.token);
                this.props.history.push(`/calculations`)
            }).catch(() => {
                this.setState({ showSuccessMessage: false })
                this.setState({ hasLoginFailed: true })
            })
    }

    render() {
        return (
            <div>
                <h1>Вход</h1>
                <div className="container">
                    {this.state.hasLoginFailed && <div className="alert alert-warning">Неверные данные</div>}
                    {this.state.showSuccessMessage && <div>Вход выполнен успешно</div>}
                    Имя пользователя: <input type="text" name="username" value={this.state.username} onChange={this.handleChange} />
                    Пароль: <input type="password" name="password" value={this.state.password} onChange={this.handleChange} />
                    <button className="btn btn-success" onClick={this.loginClicked}>Вход</button>
                </div>
            </div>
        )
    }
}

export default LoginComponent

spring 引导中的后端甚至关于 JWT 部分也很长,所以我想我会把 link 留给作为我后端基础的教程。路径有点不同,但通常这些后端部分是相同的。我也尝试使用 sessionstorage 而不是 localstorage,但没有用。如果可能的话,也许我们可以先复制整个教程代码来测试所有内容,因为那里的 jwt 部分几乎相同(我有一份副本,他们在文章中有一个 link 到他们的 github)

您可以将令牌保存在本地存储或 cookie 中。 every-time 你发送任何 xhr 请求你都可以在 header.

中传递令牌

您必须拥有登录页面,以便在登录时发送 jwt 令牌 如果以

身份登录,则在当时存储 jwt 令牌
 axios.post("http:yourAPIaddresshere", formData)
    .then((response) => {
       if(response.status === 200) {
          // storing session 
          localStorage.setItem('session', response.data.token)
          this.props.history.push('home');
        } else {
          this.showMessage('Error message', "Please check your credentials.")
        }
      } 
    });
}

这是您的会话存储在 localStorage 中的位置,现在在其他所有文件中检索令牌 在同一个登录文件中也做:

 componentDidMount(){
       if (localStorage.getItem('session') !== null) {
         this.props.history.push('home')
       }
     }

这将始终将您的导航推送到其他选项卡。 为了使您的其他 tabs/pages 安全,还要检查会话(如果不为空),它不会让您使用没有会话令牌的路由打开其他页面

 componentDidMount(){
       if (localStorage.getItem('session') === null)
     this.props.history.push('login') }

P.S: 确保在注销时清空会话令牌 as :

 localStorage.removeItem('session');