一、next-auth 身份验证凭据-使用电子邮件和密码注册登录

一、next-auth 身份验证凭据-使用电子邮件和密码注册登录

文章目录

  • 一、next-auth 身份验证凭据-使用电子邮件和密码注册登录
  • 一、前言
  • 二、前置准备
    • 1、环境配置
    • 2、相关库安装
      • (1)vercel 配置
      • (2)Yarn 包管理配置
    • 3、next项目初始化与创建
  • 三、具体实现
    • 1、github 仓库创建与链接
    • 2、Vercel项目链接Vercel账户并部署
      • (1)项目上传vercel
      • (2)项目创建并链接postgre 数据库
      • (3)本地化项目链接数据库准备
    • 3、登录页面与注册页面的前端
      • (1)登录页面
      • (1)注册页面
      • (1)register 页面
  • 四、数据库交互
    • 1、数据库创建
    • 2、vercel项目链接数据库并插入
      • (1)vercel postgre准备
      • (2) 项目注册并写sql插入数据库
      • (3) 项目查询sql数据库并登录
  • 五、状态增加
    • 1、查询到登录之后登录自动跳转状态增加
    • 2、登出与登录状态转换
    • 3、重定向
    • 4、root保护
    • 5、root保护登录页面转为自定义登录页面

一、前言

近些时间需要在next 里面加入登录注册的功能遂整理了一下学习视频:
Next auth 身份验证凭据 - 使用电子邮件和密码注册和登录(NextJS app 路由)

二、前置准备

1、环境配置

  • Vscode

  • node环境配置

  • vercel 账户注册

  • github账户注册

2、相关库安装

(1)vercel 配置

  1. npm i -g vercel //安装vercel CLI

(2)Yarn 包管理配置

  1. npm i -g yarn //安装yarn

3、next项目初始化与创建

  1. yarn create next-app

在这里插入图片描述

  1. cd nextauth-review (这里面放你写的项目名)

  2. yarn dev //运行程序,在http://localhost:3000可以查看next项目的项目名在这里插入图片描述

到这里我们就基本完成了前置的准备工作,下面继续。

三、具体实现

1、github 仓库创建与链接

在这里插入图片描述

将新建的项目上传github

在这里插入图片描述

2、Vercel项目链接Vercel账户并部署

(1)项目上传vercel

  • vercel login //vercel 登录

  • Vercel //链接与上传

在这里插入图片描述

第三行输入n。最开始的时候不连接vercel项目。

注:后续如果项目更新了,要推送到vercel部署,可以通过输入vercel ,然后在第三行输入y,并输入第一步创建的项目名。

(2)项目创建并链接postgre 数据库

在这里插入图片描述

(3)本地化项目链接数据库准备

  1. vercel env pull .env.development.local

在这里插入图片描述
注释掉VERCEL,不注释掉就会强制使用https,但我们在本地调试所以说http会报错。正式运行再取消注释。

  1. openssl rand -base64 32 ,生成32位密码,并修改.env.development.local如下:

在这里插入图片描述

  1. yarn add @types/bcrypt 安装加密工具bcrypt

  2. yarn add @vercel/postgres 安装vercel postgres

  3. yarn add next-auth 安装next-auth

到这里该项目的数据库就配置好了,下面我们开始页面开发。

3、登录页面与注册页面的前端

(1)登录页面

新建login文件夹,并在其中新建page.tsx下面是具体的内容

export default function LoginPage(){return (<form className="flex flex-col gap-2 mx-auto max-w-md mt-10"><input name='email' className ="border border-black text-black" type="email" /><input name='password' className ="border border-black text-black" type="password" /><button type="submit">Login</button></form>)
}

(1)注册页面

新建register文件夹,并在其中新建page.tsx下面是具体的内容

export default function LoginPage(){return (<form className="flex flex-col gap-2 mx-auto max-w-md mt-10"><input name='email' className ="border border-black text-black" type="email" /><input name='password' className ="border border-black text-black" type="password" /><button type="submit">Register</button></form>)
}

到这里前端就差不多了,大家可以在http://localhost:3000/login 和http://localhost:3000/register看到你写的页面

nextAuth的官方文档:https://next-auth.js.org/providers/credentials在这里插入图片描述

基本就是用来nextAuth 官方文档中的credentials 字段,结尾加上export {handler as GET, handler as POST}; 就差不多了。

类似如下:

api/auth/[…nextauth]/route.ts

import NextAuth from "next-auth/next";
import CredentialsProvider from "next-auth/providers/credentials";
const handler =NextAuth({providers: [CredentialsProvider({credentials: {email: {  },password: { }},async authorize(credentials, req) {// Add logic here to look up the user from the credentials suppliedconst user = { id: "1", name: "J Smith", email: "jsmith@example.com" }if (user) {// Any object returned will be saved in `user` property of the JWTreturn user} else {// If you return null then an error will be displayed advising the user to check their details.return null// You can also Reject this callback with an Error thus the user will be sent to the error page with the error message as a query parameter}}})]
})export {handler as GET, handler as POST};

api/auth/register/route.ts

import { NextResponse } from "next/server";export  async function POST(request : Request){try{const {email,password} = await request.json();console.log({email,password});}catch(e){console.log({e});}return NextResponse.json({message:"success"});
}

(1)register 页面

register\page.tsx

import { log } from "console";
import { FormEvent } from "react"export default function LoginPage(){const handleSubmit= async (e:FormEvent<HTMLFormElement>)=>{e.preventDefault();const formData = new FormData(e.currentTarget);const response = await fetch(`/api/auth/register`,{method:"POST",body:JSON.stringify({email:formData.get('email'),password:formData.get('password'),}),})console.log({response});}return (<form onSubmit ={ handleSubmit}className="flex flex-col gap-2 mx-auto max-w-md mt-10"><input name='email' className ="border border-black text-black" type="email" /><input name='password' className ="border border-black text-black" type="password" /><button type="submit">register</button></form>)
}

运行报错:
在这里插入图片描述

注:错误原因:需要把组件写到客户端部分,不能直接写进去Page.tsx

修改如下:

register/form.tsx

'use client'
import { FormEvent } from "react"export default function Form(){const handleSubmit = async (e:FormEvent<HTMLFormElement>) =>{e.preventDefault();const formData = new FormData(e.currentTarget);console.log(formData.get('email'),formData.get('password'));const response = await fetch(`/api/auth/register`,{method:'POST',body:JSON.stringify({email:formData.get('email'),password:formData.get('password')}),});console.log({response});};return(<form onSubmit={handleSubmit} className="flex flex-col gap-2 mx-auto max-w-md mt-10"><input name='email' className ="border border-black text-black" type="email" /><input name='password' className ="border border-black text-black" type="password" /><button type="submit">Resgiter</button></form>)
}

register/page.tsx

import Form from './form'export default async function RegisterPage(){return <Form />;}

到现在运行yarn dev 并到 http://localhost:3001/register 页面输入账户和密码,点击登录调用接口:fetch(/api/auth/register)然后打印{ email: ‘123@123’, password: ‘123’ }

在这里插入图片描述

到这里就完成简单的前后端编写,下面进入数据库交互部分。

四、数据库交互

1、数据库创建

在这里插入图片描述

依据需求创建表单users1 如上,一共有两个属性email 和password

2、vercel项目链接数据库并插入

确保Browse页面确实能查到这个新建的数据库在这里插入图片描述

(1)vercel postgre准备

yarn add @vercel/postgres

(2) 项目注册并写sql插入数据库

将API/auth/register/route.ts 的内容修改如下即可实现针对数据库的插入

import { NextResponse } from "next/server";
import {hash} from 'bcrypt'
import {sql} from '@vercel/postgres'
export  async function POST(request : Request){try{const {email,password} = await request.json();console.log({email,password});const hashedPassword = await hash(password,10); //将密码hash加密到10位const response = await sql`INSERT INTO users1 (email,password) VALUES (${email},${password})`;//${参数} 参数化查询}catch(e){console.log({e});}return NextResponse.json({message:"success"});
}

前端页面register\form.tsx 如下,page.tsx 不变

'use client'
import { signIn } from "next-auth/react";
import { FormEvent } from "react"export default function LoginForm() {const handleSubmit = async (e:FormEvent<HTMLFormElement>) =>{e.preventDefault();const formData = new FormData(e.currentTarget);signIn('credentials',{  //nextauth 登录模块email:formData.get('email'),password:formData.get('password'),redirect:false});};return(<form onSubmit={handleSubmit} className="flex flex-col gap-2 mx-auto max-w-md mt-10"><input name='email' className ="border border-black text-black" type="email" /><input name='password' className ="border border-black text-black" type="password" /><button type="submit">Login</button></form>)
}

测试的时候可以发现可以显示登录信息了

问题:发现邮箱有时候同邮箱有多个,所以需要当相同的时候就不添加而是修改

在这里插入图片描述

在数据库中限制让email唯一

(3) 项目查询sql数据库并登录

将API/auth/[…nextauth]/route.ts 的内容修改如下即可实现针对数据库的插入

import { sql } from "@vercel/postgres";
import { compare } from "bcrypt";
import NextAuth from "next-auth/next";
import CredentialsProvider from "next-auth/providers/credentials";
const handler =NextAuth({session:{strategy:'jwt'},providers: [CredentialsProvider({credentials: {email: {  },password: { }},async authorize(credentials, req) {const response = await sql`SELECT * FROM users1 WHERE email=${credentials?.email}`;const user = response.rows[0];const passwordCorrect = await compare(credentials?.password ||'',user.password);const passworduser=user.passwordconst passwordcre=credentials?.passwordconsole.log({passwordCorrect},{passwordcre},{passworduser});if (passwordCorrect){return {id:user.id,email:user.email}}//console.log({credentials}); //打印credentials信息return null}})]
})export {handler as GET, handler as POST};

前端页面login\form.tsx 如下,page.tsx 不变

'use client'
import { signIn } from "next-auth/react";
import { FormEvent } from "react"export default function LoginForm() {const handleSubmit = async (e:FormEvent<HTMLFormElement>) =>{e.preventDefault();const formData = new FormData(e.currentTarget);const response= await signIn('credentials',{  //nextauth 登录模块email:formData.get('email'),password:formData.get('password'),redirect:false});console.log({response});};return(<form onSubmit={handleSubmit} className="flex flex-col gap-2 mx-auto max-w-md mt-10"><input name='email' className ="border border-black text-black" type="email" /><input name='password' className ="border border-black text-black" type="password" /><button type="submit">Login</button></form>)
}

这时候就可以写入数据库了

五、状态增加

1、查询到登录之后登录自动跳转状态增加

解析:
如果查询到登录模块,没有返回error。则自动导航到‘/’目录同时刷新。
核心修改:

export default function LoginForm() {const router=useRouter();const handleSubmit = async (e:FormEvent<HTMLFormElement>) =>{e.preventDefault();const formData = new FormData(e.currentTarget);const response= await signIn('credentials',{  //nextauth 登录模块email:formData.get('email'),password:formData.get('password'),redirect:false});console.log({response});if(!response?.error){  //没有返回errorrouter.push('/');    //跳转到‘/’router.refresh();    //刷新缓存}};

login/form.tsx全部内容如下

'use client'
import { signIn } from "next-auth/react";
import { useRouter } from "next/navigation";
import { FormEvent } from "react"export default function LoginForm() {const router=useRouter();const handleSubmit = async (e:FormEvent<HTMLFormElement>) =>{e.preventDefault();const formData = new FormData(e.currentTarget);const response= await signIn('credentials',{  //nextauth 登录模块email:formData.get('email'),password:formData.get('password'),redirect:false});console.log({response});if(!response?.error){router.push('/');router.refresh();}};return(<form onSubmit={handleSubmit} className="flex flex-col gap-2 mx-auto max-w-md mt-10"><input name='email' className ="border border-black text-black" type="email" /><input name='password' className ="border border-black text-black" type="password" /><button type="submit">Login</button></form>)
}

2、登出与登录状态转换

登录之后,登出
登出之后,登录,并自动跳转到首页
功能解析
在全部页面都需要有这个跳转。
1、在app首页的layout.tsx页面进行编写。
2、自动跳转用next

该功能核心修改是增加:

 <nav>{!!session &&<Logout />}{!session &&<Link href='/login'>Login</Link>}</nav>

文件全部代码如下:
layout.tsx

mport type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { getServerSession } from "next-auth";
import Link from "next/link";
import Logout from "./logout";const inter = Inter({ subsets: ["latin"] });export const metadata: Metadata = {title: "Create Next App",description: "Generated by create next app",
};export default async function RootLayout({children,
}: Readonly<{children: React.ReactNode;
}>) {const session = await getServerSession();return (<html lang="en"><body className={inter.className}><nav>{!!session &&<Logout />}{!session &&<Link href='/login'>Login</Link>}</nav>{children}</body></html>);
}

由于这个里面也涉及到后端,所以需要重新编写一个的客户端API进行处理,在同目录编写
logout.tsx

'use client'import { signOut } from "next-auth/react"
export default function Logout(){return (<span onClick={() => {signOut();}}>Logout</span>)
}

到这里,登出与登录按钮增加完毕

3、重定向

当你登录后不想再返回登录页面可以参考以下的操作。
其他的网址也可以这么操作。

import { getServerSession } from "next-auth";
import Form from "./form";
import { redirect } from "next/navigation";export default async function LoginPage(){const session =await getServerSession();if(session){redirect("/")}return <Form />
}

4、root保护

一些页面需要你登录之后才能访问,在这里面我们借助中间件实现这个操作
在项目主目前增加中间件
middleware.ts

export {default } from 'next-auth/middleware'export const conifg ={matcher:['/dashboard']} //加入你要登录保护的地址

这样子,这个功能就实现完毕了。

5、root保护登录页面转为自定义登录页面

在nextauth 的route页面增加signin路径
pages:{
signIn:‘/login’,
},在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/794279.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Oracle】oracle、mysql、sql server三者区别

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Oracle》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对知识…

Shell脚本之基础-2

目录 一、字符处理 cut命令 awk命令 sed命令 字符串排序 二、条件判断 文件类型判断 文件权限判断 两个文件的判断 整数比较 字符串判断 多重判断 三、流程控制 if分支 if else 双分支结构 case分支 for循环 while循环 一、字符处理 cut命令 命令格式&#x…

深入剖析JavaScript中的this(下)

五、事件处理函数的this 5.1 事件绑定 <button id"btn">点击我</button>function handleClick(e) {console.log(this);// <button id"btn">点击我</button> }document.getElementById(btn).addEventListener(click, handleClick…

CSS基础:4种简单选择器的详解

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。大专生&#xff0c;2年时间从1800到月入过万&#xff0c;工作5年买房。 分享成长心得。 261篇原创内容-公众号 后台回复“前端工具”可获取开发工具&#xff0c;持续更新中 后台回复“前端基础…

MySQL客户端安装并配置免密登录

最近在写脚本时需要向MySQL数据库中存储数据&#xff0c;且脚本运行的服务器与MySQL服务器不是同一台服务器&#xff0c;而且需要保证MySQL密码的安全性&#xff0c;不能在脚本中暴露&#xff0c;所以就需要在服务器上安装MySQL客户端&#xff0c;并配置免密登录。 一、虚拟机…

Git安装教程(图文安装)

Git Bash是git(版本管理器)中提供的一个命令行工具&#xff0c;外观类似于Windows系统内置的cmd命令行工具。 可以将Git Bash看作是一个终端模拟器&#xff0c;它提供了类似于Linux和Unix系统下Bash Shell环境的功能。通过Git Bash&#xff0c;用户可以在Windows系统中运行基于…

Vue项目登录页实现获取短信验证码的功能

之前我们写过不需要调后端接口就获取验证码的方法,具体看《无需后端接口,用原生js轻松实现验证码》这个文章。现在我们管理后台有个需求,就是登录页面需要获取验证码,用户可以输入验证码后进行登录。效果如下,当我点击获取验证码后能获取短信验证码: 这里在用户点击获取…

Linux 线程:线程同步、生产者消费者模型

目录 一、死锁 二、条件变量实现线程同步 1、为什么需要线程同步 2、条件变量、同步、竞态条件 3、条件变量函数&#xff1a;初始化 销毁 等待 唤醒 4、实现简单的多线程程序 不唤醒则一直等待 实现线程同步 三、生产者消费者 1、借助超市模型理解 2、优点 四、基于…

数字乡村创新实践探索:科技赋能农业现代化与乡村治理体系现代化同步推进

随着信息技术的飞速发展&#xff0c;数字乡村作为乡村振兴的重要战略方向&#xff0c;正日益成为推动农业现代化和乡村治理体系现代化的关键力量。科技赋能下的数字乡村&#xff0c;不仅提高了农业生产的效率和品质&#xff0c;也为乡村治理带来了新的机遇和挑战。本文旨在探讨…

Linux 环境下 Redis基础配置及开机自启

Linux 环境下 Redis基础配置及开机自启 linux环境安装redis<redis-6.0.5.tar.gz> 1-redis基本安装配置 解压 获取到tar包后&#xff0c;解压到相关目录&#xff0c;一般是将redis目录放在usr/local/redis目录下&#xff0c;可以使用-C指定到解压下目录 tar -zvxf re…

Java数据结构栈

栈&#xff08;Stack&#xff09; 概念 栈是一种先进后出的数据结构。 栈的使用 import java.util.Stack; public class Test {public static void main(String[] args) {Stack<Integer> s new Stack();s.push(1);s.push(2);s.push(3);s.push(4);System.out.println(s…

3. python练习题3-自由落体

3. python练习题3-自由落体 【目录】 文章目录 3. python练习题3-自由落体1. 目标任务2. 解题思路3. 知识回顾-%占位符格式化处理3.1 概述3.2 占位符的多种用法3.3 格式化操作符辅助指令3.4 将整数和浮点数格式化为字符串 4. 解题思路4.1 球第1次下落4.2 球第2次下落 5. 最终代…

day60 动态规划part17

这两题看了自己写的笔记还不懂的话&#xff0c;看看这个up的思路就行&#xff1a; https://space.bilibili.com/111062940/search/video?keyword%E5%9B%9E%E6%96%87 647. 回文子串 中等 提示 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回…

学习【RabbitMQ入门】这一篇就够了

目录 1. RabbitMQ入门1-1. 同步调用1-2. 异步调用1-3. MQ技术选型1-4. RabbitMQ介绍消息模式 1-5. SpringAMQPBasic QueueWork QueueFanout ExchangeDirect ExchangeTopic Exchange消息转换器 1. RabbitMQ入门 1-1. 同步调用 优势&#xff1a; 时效性强&#xff0c;等待到结…

Windows 2008虚拟机安装、安装VM Tools、快照和链接克隆、添加硬盘修改格式为GPT

一、安装vmware workstation软件 VMware workstation的安装介质&#xff0c;获取路径&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1AUAw_--yjZAUPbsR7StOJQ 提取码&#xff1a;umz1 所在目录&#xff1a;\vmware\VMware workstation 15.1.0 1.找到百度网盘中vmwa…

Mysql的基本命令

1 服务相关命令 命令描述systemctl status mysql查看MySQL服务的状态systemctl stop mysql停止MySQL服务systemctl start mysql启动MySQL服务systemctl restart mysql重启MySQL服务ps -ef | grep mysql查看mysql的进程mysql -uroot -hlocalhost -p123456登录MySQLhelp显示MySQ…

8.list容器的使用

文章目录 list容器1.构造函数代码工程运行结果 2.赋值和交换代码工程运行结果 3.大小操作代码工程运行结果 4.插入和删除代码工程运行结果 5.数据存取工程代码运行结果 6.反转和排序代码工程运行结果 list容器 1.构造函数 /*1.默认构造-无参构造*/ /*2.通过区间的方式进行构造…

java-网络编程socket-聊天室-03

完整版代码 java -聊天室的代码: 用于存放聊天室的项目的代码和思路导图https://gitee.com/to-uphold-justice-for-others/java---code-for-chat-rooms.git 多线程并发问题 多线程的并发问题主要出现在当一个程序涉及多个线程同时运行时&#xff0c;这些线程可能会同时访问共…

Java:接口应用(Clonable 接口和深拷贝)

目录 1.引例2.Object中clone方法的实现3.Cloneable接口讲解4.深拷贝和浅拷贝4.1浅拷贝4.2深拷贝 1.引例 Java 中内置了一些很有用的接口, Clonable 就是其中之一. Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 “拷贝”. 但是要想合法调用 clone 方法。必…

精密电阻阻值表和电容容值表

前面2张是电阻阻值表&#xff08;E-96/0603/1%&#xff09; 常见贴片电容的容值表