重定向及新开标签页认证

41 阅读2分钟

请求状态码

  HTTP 301 Moved Permanently 说明请求的资源已经被移动到了由 Location 头部指定的 url 上,是固定的不会再改变。

  HTTP 302 Found 重定向状态码表明请求的资源被暂时的移动到了由该 HTTP 响应的响应头 Location 指定的 URL 上。

服务端重定向

  一开始认为后端通过设置 302 状态码及 location 后,前端页面就会自动跳转至 location 页面。多次尝试无果后去请教小助理,回复如下:

20240112.png

  于是调整了思路,实现了小助理说的两种方案。如下:

a 标签跳转

<template>
  <a href="http://localhost:3000/redirect?redirect_url=/about">
    点击a标签时重定向至about页面
  </a>
</template>

JavaScript 手动跳转

<template>about</template>

<script setup>
import axios from "axios";

axios
  .get("http://localhost:3000/redirect", {
    params: {
      redirect_url: "/detail",
    },
  })
  .then((res) => {
    // 这里相当于是获取重定向之后的请求
    window.location = res.request.responseURL;
  });
</script>

服务端代码

const Koa = require("koa");
const Router = require("koa-router");
const cors = require("@koa/cors");

const app = new Koa();
const router = new Router();

app.use(cors({ origin: "*" }));

router.get("/redirect", async (ctx, next) => {
  const { redirect_url } = ctx.request.query;
  ctx.status = 301;
  ctx.set("Location", "http://localhost:5173" + redirect_url); // 设置重定向的目标 URL
});

app.use(router.routes());
app.use(router.allowedMethods());

// 监听3000端口
app.listen(3000, () => {
  console.log("Server is running at http://localhost:3000");
});

  写完后总感觉很变扭。

新开标签认证

  即从登录页点击数字证书登录,打开新标签页进行认证。认证成功后,新标签页关闭,登录页跳转至首页。

  • 登录页如下
<template>
  <button @click="openBPage">数字证书认证</button>
</template>

<script setup>
let bWindow = null;

const openBPage = () => {
  bWindow = window.open("/certificate?userId=123", "_blank");
};

const ws = new WebSocket("ws://localhost:3000?userId=123");

ws.onopen = (event) => {
  ws.send("Hello, server!");
};

ws.onmessage = function (event) {
  if (event.data === "认证成功") {
    // 关闭 B 标签页
    bWindow.close();
    // A 标签页跳转至首页
    window.location.href = "http://localhost:5173";
  }
};

ws.onclose = (event) => {
  console.log("连接关闭");
};

ws.onerror = (event) => {
  console.error("连接发生错误:", event);
};
</script>
  • 认证标签页
<template>
  <p>数字证书认证页</p>
</template>

<script setup>
import axios from "axios";
import { useRoute } from "vue-router";

const route = useRoute();
const userId = route.query.userId;

axios
  .post("http://localhost:3000/auth", {
    userId,
  })
  .then((res) => {
    console.log(res.data);
  })
  .catch((error) => {
    console.log(error);
  });
</script>
  • 对应服务端代码
const Koa = require("koa");
const Router = require("koa-router");
const cors = require("@koa/cors");
const WebSocket = require("ws");
const http = require("http");
const bodyParser = require("koa-bodyparser");

const app = new Koa();
const router = new Router();

const sockets = {}; // 将 sockets 对象设置为全局变量

app.use(cors({ origin: "*" }));
app.use(bodyParser()); // 使用 koa-bodyparser 中间件

router.post("/auth", (ctx, next) => {
  const { userId } = ctx.request.body;
  sockets[userId].send("认证成功");
  ctx.body = {
    code: 0,
    msg: "认证成功",
  };
});

app.use(router.routes());
app.use(router.allowedMethods());

// 创建一个原生的HTTP服务器来处理Koa应用和WebSocket
const server = http.createServer(app.callback());

const wss = new WebSocket.Server({ server });

wss.on("connection", (ws, request) => {
  let userId = new URL(request.url, "ws://localhost:3000").searchParams.get(
    "userId"
  );
  sockets[userId] = ws;

  ws.send("连接成功");

  ws.on("message", (message) => {
    console.log("received: %s", message);
  });
});

// 监听3000端口
server.listen(3000, () => {
  console.log("Server is running at http://localhost:3000");
});

对应源代码链接