网站制作的主要技术,福州网站外包,2019年云南建设银行招聘网站,做系统去哪个网站一、next-auth 身份验证凭据-使用电子邮件和密码注册登录 文章目录 一、next-auth 身份验证凭据-使用电子邮件和密码注册登录一、前言二、前置准备1、环境配置2、相关库安装#xff08;1#xff09;vercel 配置#xff08;2#xff09;Yarn 包管理配置 3、next项目初始化与…一、next-auth 身份验证凭据-使用电子邮件和密码注册登录 文章目录 一、next-auth 身份验证凭据-使用电子邮件和密码注册登录一、前言二、前置准备1、环境配置2、相关库安装1vercel 配置2Yarn 包管理配置 3、next项目初始化与创建 三、具体实现1、github 仓库创建与链接2、Vercel项目链接Vercel账户并部署1项目上传vercel2项目创建并链接postgre 数据库3本地化项目链接数据库准备 3、登录页面与注册页面的前端1登录页面1注册页面1register 页面 四、数据库交互1、数据库创建2、vercel项目链接数据库并插入1vercel postgre准备2 项目注册并写sql插入数据库3 项目查询sql数据库并登录 五、状态增加1、查询到登录之后登录自动跳转状态增加2、登出与登录状态转换3、重定向4、root保护5、root保护登录页面转为自定义登录页面 一、前言
近些时间需要在next 里面加入登录注册的功能遂整理了一下学习视频 Next auth 身份验证凭据 - 使用电子邮件和密码注册和登录NextJS app 路由
二、前置准备
1、环境配置 Vscode node环境配置 vercel 账户注册 github账户注册
2、相关库安装
1vercel 配置
npm i -g vercel //安装vercel CLI
2Yarn 包管理配置
npm i -g yarn //安装yarn
3、next项目初始化与创建
yarn create next-app cd nextauth-review (这里面放你写的项目名) 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本地化项目链接数据库准备
vercel env pull .env.development.local 注释掉VERCEL不注释掉就会强制使用https但我们在本地调试所以说http会报错。正式运行再取消注释。
openssl rand -base64 32 生成32位密码并修改.env.development.local如下 yarn add types/bcrypt 安装加密工具bcrypt yarn add vercel/postgres 安装vercel postgres yarn add next-auth 安装next-auth
到这里该项目的数据库就配置好了下面我们开始页面开发。
3、登录页面与注册页面的前端
1登录页面
新建login文件夹并在其中新建page.tsx下面是具体的内容
export default function LoginPage(){return (form classNameflex flex-col gap-2 mx-auto max-w-md mt-10input nameemail className border border-black text-black typeemail /input namepassword className border border-black text-black typepassword /button typesubmitLogin/button/form)
}1注册页面
新建register文件夹并在其中新建page.tsx下面是具体的内容
export default function LoginPage(){return (form classNameflex flex-col gap-2 mx-auto max-w-md mt-10input nameemail className border border-black text-black typeemail /input namepassword className border border-black text-black typepassword /button typesubmitRegister/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: jsmithexample.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});
}1register 页面
register\page.tsx
import { log } from console;
import { FormEvent } from reactexport default function LoginPage(){const handleSubmit async (e:FormEventHTMLFormElement){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}classNameflex flex-col gap-2 mx-auto max-w-md mt-10input nameemail className border border-black text-black typeemail /input namepassword className border border-black text-black typepassword /button typesubmitregister/button/form)
}运行报错
注错误原因需要把组件写到客户端部分不能直接写进去Page.tsx
修改如下
register/form.tsx
use client
import { FormEvent } from reactexport default function Form(){const handleSubmit async (e:FormEventHTMLFormElement) {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} classNameflex flex-col gap-2 mx-auto max-w-md mt-10input nameemail className border border-black text-black typeemail /input namepassword className border border-black text-black typepassword /button typesubmitResgiter/button/form)
}register/page.tsx
import Form from ./formexport default async function RegisterPage(){return Form /;}到现在运行yarn dev 并到 http://localhost:3001/register 页面输入账户和密码点击登录调用接口fetch(/api/auth/register)然后打印{ email: ‘123123’, password: ‘123’ } 到这里就完成简单的前后端编写下面进入数据库交互部分。
四、数据库交互
1、数据库创建 依据需求创建表单users1 如上一共有两个属性email 和password
2、vercel项目链接数据库并插入
确保Browse页面确实能查到这个新建的数据库
1vercel 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 sqlINSERT 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 reactexport default function LoginForm() {const handleSubmit async (e:FormEventHTMLFormElement) {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} classNameflex flex-col gap-2 mx-auto max-w-md mt-10input nameemail className border border-black text-black typeemail /input namepassword className border border-black text-black typepassword /button typesubmitLogin/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 sqlSELECT * FROM users1 WHERE email${credentials?.email};const user response.rows[0];const passwordCorrect await compare(credentials?.password ||,user.password);const passworduseruser.passwordconst passwordcrecredentials?.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 reactexport default function LoginForm() {const handleSubmit async (e:FormEventHTMLFormElement) {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} classNameflex flex-col gap-2 mx-auto max-w-md mt-10input nameemail className border border-black text-black typeemail /input namepassword className border border-black text-black typepassword /button typesubmitLogin/button/form)
}这时候就可以写入数据库了
五、状态增加
1、查询到登录之后登录自动跳转状态增加
解析 如果查询到登录模块没有返回error。则自动导航到‘/’目录同时刷新。 核心修改
export default function LoginForm() {const routeruseRouter();const handleSubmit async (e:FormEventHTMLFormElement) {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 reactexport default function LoginForm() {const routeruseRouter();const handleSubmit async (e:FormEventHTMLFormElement) {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} classNameflex flex-col gap-2 mx-auto max-w-md mt-10input nameemail className border border-black text-black typeemail /input namepassword className border border-black text-black typepassword /button typesubmitLogin/button/form)
}2、登出与登录状态转换
登录之后登出 登出之后登录,并自动跳转到首页 功能解析 在全部页面都需要有这个跳转。 1、在app首页的layout.tsx页面进行编写。 2、自动跳转用next
该功能核心修改是增加 nav{!!session Logout /}{!session Link href/loginLogin/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 langenbody className{inter.className}nav{!!session Logout /}{!session Link href/loginLogin/Link}/nav{children}/body/html);
}由于这个里面也涉及到后端所以需要重新编写一个的客户端API进行处理在同目录编写 logout.tsx
use clientimport { 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/middlewareexport const conifg {matcher:[/dashboard]} //加入你要登录保护的地址这样子这个功能就实现完毕了。
5、root保护登录页面转为自定义登录页面
在nextauth 的route页面增加signin路径 pages:{ signIn:‘/login’, },