nestjs中使用session获取不到值的问题

242 阅读1分钟
最近在学习nestjs,在学习使用验证码登录设置验证码session的值,遇到的问题以及是怎样解决

Snipaste_2024-05-10_09-15-10.png

前端登录页面

<!--
 * @Description: 
 * @Author: HYH
 * @LastEditors: HYH
 * @LastEditTime: 2023-06-08 10:52:05
-->
<template>
  <main class="w-screen h-screen flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
    <div class="sm:mx-auto sm:w-full sm:max-w-md">
      <el-form
        status-icon
        size="large"
        ref="formRef"
        label-position="top"
        :model="loginForm"
        :rules="rules"
        class="bg-white/40 rounded-2xl shadow-2xl p-7 pt-10">
        <el-form-item>
          <div class="w-full font-bold text-[30px] text-center text-bg">登 录</div>
        </el-form-item>
        <el-form-item prop="email" label="邮箱">
          <el-input v-model="loginForm.email" />
        </el-form-item>
        <el-form-item prop="password" label="密码">
          <el-input v-model="loginForm.password" type="password" />
        </el-form-item>
        <el-form-item class="captcha" prop="captcha" label="验证码">
          <el-input v-model="loginForm.captcha" placeholder="请输入">
            <template #append>
              <img
                style="width: 150px"
                :src="getCaptchaUrl"
                alt=""
                @click="(e:any)=>e.target.src = getCaptchaUrl + `?timeStamp=${Date.now()}`" />
            </template>
          </el-input>
        </el-form-item>
        <el-form-item>
          <div class="flex w-full justify-between">
            <div><input type="checkbox" :checked="checked" /><span class="ml-2">记住密码</span></div>
            <a href="#resetPwd" class="text-[#1e80ff] font-bold">忘记密码?</a>
          </div>
        </el-form-item>
        <el-form-item>
          <el-button class="w-full !text-lg" color="#626aef" @click="login">login</el-button>
        </el-form-item>
        <el-form-item>
          <div class="text-sm text-gray-500">
            没有账号?
            <a href="#regist" class="font-semibold leading-6 text-indigo-600"> 点击注册 </a>
          </div>
        </el-form-item>
      </el-form>
    </div>
  </main>
</template>
<script setup lang="ts">
import useKeyDown from '@/hooks/useKeyDown'
import useValidate from '@/hooks/useValidate'
import { http } from '@/http'
import userStore from '@/store/user'
import { ElMessage, FormInstance } from 'element-plus'
import { useRouter } from 'vue-router'
const store = userStore()
const router = useRouter()
const getCaptchaUrl = ref(import.meta.env.VITE_BASE_URL + import.meta.env.VITE_BASE_API + '/login/captcha')
const formRef = ref<FormInstance>()

const loginForm = reactive({
  email: '',
  password: '',
  captcha: '',
})

const rules = reactive<any>({
  email: useValidate.email,
  password: useValidate.password,
  captcha: useValidate.pleaseInput,
})

const checked = ref(true)

const login = () => {
  formRef.value.validate((valid) => {
    if (valid) {
      http.post<UserModel>('/api/login', loginForm).then((res) => {
        const { code, data } = res
        if (code === 200) {
          store.setInfo(data)
          router.push({ name: 'dashboard', replace: true })
        }
      })
    }
  })
}

useKeyDown((e) => {
  e.key == 'Enter' && login()
})

onMounted(() => {})
</script>

<style lang="scss" scoped>
:deep(.captcha) {
  cursor: pointer;
  .el-form-item__content {
    .el-input-group__append {
      padding: 0;
    }
  }
}
</style>

vite 配置 (如果不配置proxy会提示跨域问题,试了一下服务器配置,发现不生效)

/*
 * @Description:
 * @Author: HYH
 * @LastEditors: HYH
 * @LastEditTime: 2023-07-28 20:08:45
 */
import path, { resolve } from 'path'
import fs from 'fs'
import { defineConfig, loadEnv, searchForWorkspaceRoot } from 'vite'
import usePlugin from './vite/usePlugin'

// @ts-ignore
export default defineConfig(({ command, mode, ssrBuild }) => {
  /**根据 "mode" 值 读取获取本地环境变量中的.env.[mode]中 VITE_BASE_URL 的值 */
  const env = loadEnv(mode, process.cwd())
  console.log({
    mode,
    command,
  })
  const isProduction = mode === 'production'

  return {
    // 生产或开发环境下的基础路径
    // base: '/doc',
    // 需要用到的插件数组
    plugins: usePlugin(isProduction),
    server: {
      proxy: {
        '/api': {
          target: env.VITE_BASE_URL + '/api',
          changeOrigin: true,
          rewrite: (path) => path.replace(/^\/api/, ''),
        },
      },
      // https: {
      //   cert: fs.readFileSync(path.join(__dirname, './keys/cert.crt')),
      //   key: fs.readFileSync(path.join(__dirname, './keys/cert.key')),
      // },
      host: true,
      port: env.VITE_FRONT_PORT,
      /**可读取的文件夹 */
      fs: {
        allow: [searchForWorkspaceRoot(process.cwd()), '../app/enum'],
      },
    },

    //
    resolve: {
      // 设置文件目录别名
      alias: {
        '@': resolve(__dirname, './src'),
        '~': resolve(__dirname, './'),
        '@@': resolve(__dirname, '../server'),
      },
      extensions: ['.js', '.ts', '.tsx', '.jsx'],
      //
    },
    build: {
      // outDir: path.join(__dirname, '../docBuild/koa_ts_server_full_doc'),
      emptyOutDir: true,
      rollupOptions: {
        output: {
          chunkFileNames: 'js/[name]-[hash].js', // 引入文件名的名称
          entryFileNames: 'js/[name]-[hash].js', // 包的入口文件名称
          assetFileNames: '[ext]/[name]-[hash].[ext]', // 资源文件像 字体,图片等
          /**
           * @description  清除文件名格式不正确问题
           * @param name
           * @returns
           */
          // https://github.com/rollup/rollup/blob/master/src/utils/sanitizeFileName.ts
          sanitizeFileName(name) {
            // eslint-disable-next-line no-control-regex
            const INVALID_CHAR_REGEX = /[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g
            const DRIVE_LETTER_REGEX = /^[a-z]:/i
            const match = DRIVE_LETTER_REGEX.exec(name)
            const driveLetter = match ? match[0] : ''
            // A `:` is only allowed as part of a windows drive letter (ex: C:\foo)
            // Otherwise, avoid them because they can refer to NTFS alternate data streams.
            let file = driveLetter + name.slice(driveLetter.length).replace(INVALID_CHAR_REGEX, '')
            if (file.startsWith('_')) file = file.slice(1) /**去除首位字符串为 "_" , fix github page访问不了的问题*/
            return file
          },

          // // 最小化拆分包
          // manualChunks(id) {
          //   if (id.includes('node_modules')) {
          //     return id.toString().split('node_modules/')[1].split('/')[0].toString()
          //   }
          // },
        },
      },
    },
    esbuild: {
      // drop: isProduction ? ['console', 'debugger'] : [], // 删除 所有的console 和 debugger
    },
  }
})

后端nestjs

import { Body, Controller, Get, Post, Res, Session } from '@nestjs/common';
import { Response } from 'express';
import { LoginService } from './login.service';

import { ApiTags } from '@nestjs/swagger';
// import { LoginPipe } from './login.pipe';

@Controller('login')
@ApiTags('登录接口')
export class LoginController {
  constructor(private readonly loginService: LoginService) {}

  @Post()
  login(@Body() dto, @Session() session) {
    const { captcha } = dto;
    if (captcha != session.captcha) {
      return '验证码错误';
    }
    // return this.loginService.login(dto);
  }

  @Get('captcha')
  captcha(@Res() res: Response, @Session() session) {
    const captcha = this.loginService.captcha();
    session.captcha = captcha.text;
    res.type('image/svg+xml');
    res.send(captcha.data);
  }
}

问题复现

使用localhost打开项目,一直拿不到session

改成ip之后就可以了

就这么解决了 哈哈