IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> JWT实现跨域请求 -> 正文阅读

[JavaScript知识库]JWT实现跨域请求

JWT实现跨域请求



cookie的弊端

最近在做一个web项目,我想实现一个功能:客户端浏览器每次访问首页的时候,就从请求中获取cookie,如果cookie中含有用户信息,就自动为用户登录,否则就不登陆。
但是我的前端是基于vue实现的,起在8080端口,服务端起在9090端口,众所周知cookie是不可以跨域的,满足不同协议,不同域名,不同端口即为跨域,虽然前后端都部署在localhost,但是不同端口造成了跨域。

虽然我们可以采取cors策略等办法实现跨域,但是相对来说增添了麻烦。

使用JWT实现跨域

我采取了网上的很多办法,依然不能让cookie实现跨域,于是就想到了使用JWT+localStorage的办法。其实JWT是可以放在cookie里面的,但是在本文的场景中cookie不能跨域。

大致思路是这样的:

  1. 用户登录成功以后,服务端把用户的手机号码生成一个Token令牌,然后返回给客户端浏览器。
  2. 客户端浏览器在收到服务端的response以后,把Token令牌储存到localStorage中,但是localStorage默认是没有过期时间的,也就是永久保存,所以我们还需要做一层封装,维护一个过期时间。
  3. 下一次用户访问首页的时候,如果储存的token没有过期,就把token令牌储存在request中。
  4. 服务端获取到request中的token令牌,如果正确,就自动为用户登录

案例

在这里我做了一个简单的小demo来演示大致的流程,用了gin、vue以及一个go的jwt库:Gin中使用JWT

客户端

首先在前端创建一个storage.js文件来对localStorage做一次封装:

<template>
    <div class="form">
        <input type="text" v-model="phoneNumber">
        <input type="submit" value="提交" @click="submit">
        <br>

        <br>

        <input type="submit" value="第二次提交" @click="submit2">

    </div>
</template>

<script>
import storage from '../../assets/storage'
export default {
    data() {
        return {
            phoneNumber: null,
        }
    },
    methods: {
        submit() {
            var forms = new FormData();
            forms.append("phoneNumber", this.phoneNumber);
            this.$axios.post("http://127.0.0.1:9092/token", forms).then((res) => {
                storage.set("access_token", res.data.token)
                console.log("后端发送来的token储存到本地:");
                console.log(res.data.token);
            })
        },
        submit2() {
            var forms = new FormData();
            forms.append("Authorization", 'Bearer ' + storage.get("access_token"))
            console.log("从浏览器缓存取出token发送:" + forms.get("Authorization"));
            this.$axios.post("http://127.0.0.1:9092/token2", forms).then((res) => {
                console.log("打印后端的数据:");
                console.log(res.data.message);
            })
        },
    }
}
</script>

在这里插入图片描述
服务端

首先创建一个jwt的model在token.go文件中,我们在里面定义了jwt结构体、生成token令牌的方法以及解析token令牌的方法:

package models

import (
	"errors"
	"github.com/dgrijalva/jwt-go"
	"time"
)

// MyClaims 自定义结构体
type MyClaims struct {
	PhoneNumber string `json:"phoneNumber"`
	jwt.StandardClaims
}

const TokenExpireDuration = time.Hour * 720
// 自定义密钥
var mySecret = []byte("123456")

// GenToken 生成jwt
func GenToken(phoneNumber string) (string, error)  {
	c := MyClaims{
		phoneNumber,
		jwt.StandardClaims {
			ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(),  // 过期时间
			Issuer: "goShop",   // 签发人
		},
	}
	// 使用HS256加密方式
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
	tmp, err := token.SignedString(mySecret)
	return tmp, err
}

// ParseToken 解析token
func ParseToken(tokenString string) (*MyClaims, error)  {
	token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (interface{}, error) {
		return mySecret, nil
	})
	if err != nil {
		return nil, err
	}
	if Claims, ok := token.Claims.(*MyClaims); ok && token.Valid {
		return Claims, nil
	}
	return nil, errors.New("invalid token")
}

最后我们在入口函数中定义接受客户端两次请求的路由:

package tests

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"go-shop/middleware"
	"go-shop/models"
	"net/http"
	"testing"
)

func authHandler(c *gin.Context)  {
	phoneNumber := c.PostForm("phoneNumber")
	// 生成token
	tokenString, _ := models.GenToken(phoneNumber)
	fmt.Println("生成token:", tokenString)
	c.JSON(http.StatusOK, gin.H{
		"msg" : "success",
		"token" : tokenString,
	})
}
func authHandler2(c *gin.Context)  {
	fmt.Println("token认证成功!")
	c.JSON(http.StatusOK, gin.H{
		"message" : "success",
	})
}

func TestJWT(t *testing.T) {
	r := gin.Default()
	r.Use(middleware.Cors())
	r.POST("/token", authHandler)
	r.POST("/token2", middleware.JWTAuthMiddleware(),authHandler2)
	r.Run(":9092")
}

在表单中输入我的手机号码,然后点击提交,服务端会生成一段token令牌发送回来:
在这里插入图片描述然后点击第二次提交按钮,客户端会把令牌从localStorage中提取出来,加在request中发送给服务端,服务端验证成功以后,发送反馈消息:

在这里插入图片描述

参考资料:

vue-localStorage 缓存过期时间

vue保存后端发来的token+vue向后端发送网络请求携带token

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-28 11:44:26  更:2022-04-28 11:45:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:20:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码