Nuxt3与SpringBoot登录认证集成

简述

登录认证是所有系统都会涉及到的问题,牵扯到的知识点有: 密码加密、cookie、session、token、JWT等。
在前后端不分离的应用中,基于Cookie-Session机制能较容易实现会话跟踪和token认证。但前后端分离后,需要前端主动发送cookie或请求头加上token信息才能维持会话。
基于Cookie-Session机制的登录场景有:

  • 前后端同域——与普通登录没有区别
  • 前后端不同域:
    • JSONP方式实现
    • CORS方式实现

Nuxt 3 comes with built-in utilities to support session and authentication. We are working on a new official module.

SpringBoot端开发配置

采用sa-token认证框架

Nuxt端

封装$fetch,在请求头里统一加上token

import { Message } from '@arco-design/web-vue'
import type { FetchResponse, SearchParameters } from 'ofetch'
import type { Ref } from 'vue'
import type { UseFetchOptions } from '#app'
import { PageEnum } from '~/enums/pageEnum'
import { RequestEnum, ResultEnum } from '~/enums/httpEnum'
import { useUserStore } from '~/stores/user.store'
import IconEmoticonDead from '~icons/mdi/emoticon-dead'


export interface ResOptions<T> {
  data?: T
  code?: number
  message?: string
  success?: boolean
}

type UrlType = string | Request | Ref<string | Request> | (() => string | Request)


export type HttpOption<T> = UseFetchOptions<ResOptions<T>>


const handleError = <T>(response: FetchResponse<ResOptions<T>> & FetchResponse<ResponseType>) => {
  const err = (text: string) => {
    Message.error({
      content: response?._data?.message ?? text,
      icon: () => h(IconEmoticonDead),
    })
  }
  if (!response._data) {
    err('请求超时,服务器无响应!')
    return
  }
  const userStore = useUserStore()
  const handleMap: { [key: number]: () => void } = {
    404: () => err('服务器资源不存在'),
    500: () => err('服务器内部错误'),
    403: () => err('没有权限访问该资源'),
    401: () => {
      err('登录状态已过期,需要重新登录')
      userStore.clearUserInfo()
      // TODO 跳转实际登录页
      navigateTo('/')
    },
  }
  handleMap[response.status] ? handleMap[response.status]() : err('未知错误!')
}

// get方法传递数组形式参数
const paramsSerializer = (params?: SearchParameters) => {
  if (!params)
    return

  const query = useCloneDeep(params)
  Object.entries(query).forEach(([key, val]) => {
    if (typeof val === 'object' && Array.isArray(val) && val !== null) {
      query[`${key}[]`] = toRaw(val).map((v: any) => JSON.stringify(v))
      delete query[key]
    }
  })
  return query
}


const fetch = <T>(url: UrlType, option: UseFetchOptions<ResOptions<T>>) => {
  return useFetch<ResOptions<T>>(url, {
    // 请求拦截器
    onRequest({ options }) {
      // get方法传递数组形式参数
      options.params = paramsSerializer(options.params)
      // 添加baseURL,nuxt3环境变量要从useRuntimeConfig里面取
      const { public: { apiBase } } = useRuntimeConfig()
      options.baseURL = apiBase
      // 添加请求头,没登录不携带token
      const userStore = useUserStore()
      if (!userStore.isLogin)
        return
      options.headers = new Headers(options.headers)
      options.headers.set('Authorization', `Bearer ${userStore.getToken}`)
    },
    // 响应拦截
    onResponse({ response }) {
      if (response.headers.get('content-disposition') && response.status === 200)
        return response
      // 在这里判断错误
      if (response._data.code !== 200) {
        handleError<T>(response)
        return Promise.reject(response._data)
      }
      // 成功返回
      return response._data
    },
    // 错误处理
    onResponseError({ response }) {
      handleError<T>(response)
      return Promise.reject(response?._data ?? null)
    },
    // 合并参数
    ...option,
  })
}

// 自动导出
export const useHttp = {
  get: <T>(url: UrlType, params?: any, option?: HttpOption<T>) => {
    return fetch<T>(url, { method: 'get', params, ...option })
  },

  post: <T>(url: UrlType, body?: any, option?: HttpOption<T>) => {
    return fetch<T>(url, { method: 'post', body, ...option })
  },

  put: <T>(url: UrlType, body?: any, option?: HttpOption<T>) => {
    return fetch<T>(url, { method: 'put', body, ...option })
  },

  delete: <T>(url: UrlType, body?: any, option?: HttpOption<T>) => {
    return fetch<T>(url, { method: 'delete', body, ...option })
  },
}

参考链接

【资源说明】 1、基于SpringBoot+Nuxt的服务端渲染博客系统源码+数据库+项目说明.zip 2、该资源包括项目的全部源码,下载可以直接使用! 3、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 4、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。 基于SpringBoot+Nuxt的服务端渲染博客系统源码+数据库+项目说明.zip ### 简介 基于 SpringBootNuxt 的前后端分离博客 ### SQL文件 blog.sql 初始账号密码:Linter ### Nginx配置 ``` location / { proxy_pass http://127.0.0.1:3000; } location ~ .*\.(gif|jpg|jpeg|png)$ { proxy_pass http://127.0.0.1:3000; } location ~ .*\.(js|css|woff|ttf|ico)?$ { proxy_pass http://127.0.0.1:3000; } ``` ### 截图 #### 首页 ![首页](screenshot/blog-index.png) #### 登录 ![登录](screenshot/blog-login.png) #### 分类 ![分类](screenshot/blog-catalog.png) #### 文章 ![文章](screenshot/blog-article.png) #### 评论 ![评论](screenshot/blog-comment-new.png) #### 搜索 ![搜索](screenshot/blog-search.png) #### 后台首页 ![后台首页](screenshot/blog-admin-index.png) #### 发布文章 ![发布文章](screenshot/blog-article-new.png) #### 文章管理 ![文章管理](screenshot/blog-article-list.png) #### 新增分类 ![新增分类](screenshot/blog-category-new.png) #### 编辑分类 ![编辑分类](screenshot/blog-category-edit.png) #### 分类管理 ![分类管理](screenshot/blog-category-list.png) #### 评论管理 ![评论管理](screenshot/blog-comment-list.png) #### 新增用户 ![新增用户](screenshot/blog-user-new.png) #### 用户管理 ![用户管理](screenshot/blog-user-list.png)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北极象

如果觉得对您有帮助,鼓励一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值