【问题标题】:Redirect to another page with TOKEN header through Server通过服务器重定向到带有 TOKEN 标头的另一个页面
【发布时间】:2021-03-16 03:04:20
【问题描述】:

我的目标是重定向到主页“/”
但是“/”页面附有中间件检查用户是否有TOKEN

我想重定向到“/”带有 Bearer TOKEN 标头
不带 AJAX

所以,我在服务器上新建了一个路径“/loginDetour”
并通过 TOKEN Header
使用 FETCH 到此路径 然后,"/loginDetour"server 使页面重定向到“/”

但是....它不起作用..
这是我的代码

主路由器

const express = require('express');
const app = express();
const hbs = require('express-handlebars');
const path = require('path');
const PORT = process.env.PORT || 5000;

const layoutsDir = path.join(__dirname, './views/layouts');
const partialsDir = path.join(__dirname, './views/partials');
const publicPath = path.join(__dirname, './public');

const authRouter = require('./server/routes/authRouter');
const weatherRouter = require('./server/routes/weatherRouter');
const todoRouter = require('./server/routes/todoRouter');

app.set('view engine', 'hbs');
app.engine(
  'hbs',
  hbs({
    extname: 'hbs',
    defaultLayout: 'layout',
    layoutsDir,
    partialsDir,
  })
);
if (process.env.NODE_ENV === 'production') {
  app.get('view cache');
}

app.use(express.static(publicPath));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

const checkAuth = require('./server/middleware');
app.use(authRouter.routes);
app.use('/weather', checkAuth, weatherRouter.routes);
app.use('/todo', checkAuth, todoRouter.routes);

app.get('/', checkAuth, (req, res) => {
  res.render('index');
});

app.listen(PORT, () => {
  console.log(`Server started on Port ${PORT}`);
});

登录路由器

router.post('/login', async (req, res) => {
  try {
    const { email, password } = req.body;
    await auth.signInWithEmailAndPassword(email, password);
    const token = await auth.currentUser.getIdToken(true);

    return res.json(token)

  } catch (err) {
    res.status(400).render('login', {
      err: err.message,
      style: 'login',
      isRegister: false,
      type: 'Login',
    });
  }
});

router.get('/loginDetour', async (req, res) => {
  try {
    const tokenBearered = req.headers.authorization;
    res.setHeader('Authorization', tokenBearered);
    return res.status(302).redirect('/');
  } catch (err) {
    res.status(400).json({ errMsg: error.message });
  }
});

中间件

const checkAuth = async (req, res, next) => {
if (!req.headers.authorization) {
    return res.redirect('/login');
  }
  const token = req.headers.authorization.split('Bearer ')[1];
  const decoded = await admin.auth().verifyIdToken(token);

  if (!decoded.uid) {
    return res.redirect('/login');
  }
  // const userRecord = await admin.auth().getUser(decoded.uid);
  // console.log(userRecord.toJSON());
  req.uid = decoded.uid;
  next();
};

module.exports = checkAuth;

前台(登录)
1.登录
2.fetch到POST'/login'
3.Server给TOKEN & Save到本地
4.使用令牌头获取 GET'/loginDetour'
3.服务器重定向到'/'

<script type="module">
    import { errAlert } from './js/errAlert.js'
    import { defaultHeader }from './js/auth/auth.js'

    const form = document.querySelector('.login-form')
    const isRegister = {{isRegister}}

    const authHandler = async(e) =>{
        e.preventDefault();
        const email = form['email'].value;
        const password = form['password'].value;
        let userName = ''
        let password2 =''
        if(isRegister){
            userName = form['userName'].value;
            password2 = form['password2'].value;
            if(password !== password2){
                errAlert("Password and Confirmed doesn't matched", 4000)
            }
        }
        const url = isRegister ? '/register' : '/login'
        const config = {
            method: 'POST',
            body: JSON.stringify({ email, password, userName }),
            headers: {
            'Content-Type': 'application/json',
            },
        };
        const res = await fetch(url, config)
        const token = await res.json()
        if(token){
            localStorage.setItem('token', token)
            const config = {
            method: 'GET',
            redirect: 'follow',
            headers: {
                Authorization: `Bearer ${token}`,
            }
            };
            axios('/loginDetour', config)
        }
    }
    form.addEventListener("submit", authHandler)
</script>

SOS TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

【问题讨论】:

  • 这能回答你的问题吗? stackoverflow.com/questions/66594404/…
  • 页面不会被ajax请求重定向,而是需要检查请求的状态并手动跟随重定向。或者更好,而不是向loginDetour 发出新请求,只需重定向到if (token) 块中的/
  • @FredStark 我认为stackoverflow.com/a/66595622/441757 的答案不正确。请参阅我的评论:浏览器不会将 3xx 重定向暴露给您的前端 JavaScript 代码。相反,浏览器会自动跟随重定向——因此,例如,前端 JavaScript 代码中的 if(response.status === 302) 之类的条件将永远无法达到。
  • 是的,你是对的

标签: javascript node.js redirect


【解决方案1】:

我在 cmets 中关于能够读取 3xx 响应是错误的,但是如果您允许请求遵循重定向,您可以检查 redirected 属性并访问最终的 urlhttps://developer.mozilla.org/en-US/docs/Web/API/Response/url

那么只需做一个客户端重定向:

  fetch("/loginDetour").then(res => {
    if (res.redirected) window.location = res.url;
  });

我的第一条评论仍然存在,除非您需要从服务器发回重定向 URL,否则在登录请求后进行重定向要容易得多:

        const res = await fetch(url, config)
        const token = await res.json()
        if(token){
            localStorage.setItem('token', token)
            window.location = '/';
        }

如果你有一个令牌,则表示登录成功,所以只需重定向到那里并保存一个额外的 HTTP 请求。


题外话,但除非您正在做一些时髦的跨域工作,否则将令牌放在 cookie 中要比 localstorage 好得多。

发件人:https://balavishnuvj.com/blog/where-to-store-auth-tokens/

我建议在启用 httpOnly 和 SameSite 的情况下将所有长期存在的令牌(如会话 ID、刷新令牌)存储在 Cookie 中。作为额外的安全措施,根据您使用的应用程序和库/模块,您可以启用 CSRF。

https://twitter.com/ryanflorence/status/1370435079898497025

按照教程将 JWT 放入 localStorage?

如果 UNPKG 背后的人愿意,他可以将代码注入 JS 请求 并收集所有用户的 JWT。与您的任何第 3 方脚本相同 使用。

2B req/mo 是很多代币。

我把那些废话放在签名、https、SameSite cookie 中。

【讨论】:

  • 感谢您的具体回答!但是 解决方案不起作用因为如果我使用 res.url,那一刻它需要一个令牌头
  • 这就是您应该使用 cookie 的原因。您还允许导航到/ 吗?
  • 啊哈。抱歉我误会了,我会考虑使用 Cookie 和 Cookie-parser!
猜你喜欢
  • 1970-01-01
  • 2016-10-12
  • 2020-04-21
  • 1970-01-01
  • 2015-09-24
  • 2022-11-15
  • 1970-01-01
  • 2019-09-25
  • 2022-01-27
相关资源
最近更新 更多