nextjs 实现token用户登录,cookie加密。

in nodejs with 0 comment

nextjs登录的插件很多,官方也提供了很多好几种解决方案和示例代码。
这里我们通过cookie来实现。

一、pages下新增2个文件。
login.js //登录
user.js //登录之后才可以,未登录跳转到login

二、login.js新增用户登录的代码:
安装下antd, axios, nookies

    
import React, { useState } from 'react'
import {useRouter} from 'next/router' 

import { Form, Input, Button, Checkbox, Spin, message } from 'antd';
import axios from 'axios'
import nookies, { setCookie } from 'nookies'
import {encrypt, cookie_name} from '../libs/encrypt'
 
import Head from 'next/head'
import styles from '../styles/Home.module.css'

const layout = {
    labelCol: {
      span: 8,
    },
    wrapperCol: {
      span: 16,
    },
  };
  const tailLayout = {
    wrapperCol: {
      offset: 8,
      span: 16,
    },
  };

export default function Login() {
    const router = useRouter()
    const [loading, setLoading] = useState(false)
    const onFinish = (values) => {
        console.log('Success:', values);
        setLoading(true)
        axios({
            url:'https://you_api_auth/auth/',
            method:'post',
            data:values
        }).then(res=>{
            let hashkeys =  encrypt(res.data);
            setCookie(null, cookie_name, hashkeys, {
                // maxAge: 30 * 24 * 60 * 60,
                maxAge: 3 *24 * 60 * 60, //三天
                path: '/',
            })
            message.success('登录成功!')
            setTimeout(()=>{
                router.push('/user')
            }, 1500)
            
           
        }).catch(e=>{
            console.log(e)
        }) 
    };
    
    const onFinishFailed = (errorInfo) => {
        console.log('Failed:', errorInfo);
    };
    
  return (
    <div className={styles.container}>
      <Head>
        <title>Login</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

        <Spin spinning={loading}>
        <main className={styles.main}>
            <Form
            {...layout}
            name="basic"
            initialValues={{
                remember: true,
            }}
            onFinish={onFinish}
            onFinishFailed={onFinishFailed}
            >
            <Form.Item
                label="Username"
                name="username"
                rules={[
                {
                    required: true,
                    message: 'Please input your username!',
                },
                ]}
            >
                <Input />
            </Form.Item>

            <Form.Item
                label="Password"
                name="password"
                rules={[
                {
                    required: true,
                    message: 'Please input your password!',
                },
                ]}
            >
                <Input.Password />
            </Form.Item>

            <Form.Item {...tailLayout} name="remember" valuePropName="checked">
                <Checkbox>Remember me</Checkbox>
            </Form.Item>

            <Form.Item {...tailLayout}>
                <Button type="primary" htmlType="submit">
                Submit
                </Button>
            </Form.Item>
            </Form>
        </main>
        </Spin>

      <footer className={styles.footer}>
        <a
          href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
          target="_blank"
          rel="noopener noreferrer"
        >
          Powered by{' '}
          <img src="/vercel.svg" alt="Vercel Logo" className={styles.logo} />
        </a>
      </footer>
    </div>
  )
}

export async function getServerSideProps(ctx) {
    const cookies = nookies.get(ctx)
    //login页面,如果登录了包含了cookie内容,就跳转到登录页面
    if(cookies[cookie_name]){
        return {
            redirect: {
              destination: '/user',
              permanent: false,
            },
          }
    }
    return { props:{} }
}

encrypt.js 代码:

import CryptoJS  from 'crypto-js'


const my_secret_string = 'dsds%$54sjdjssd2323232k232!23sdjk@'
const cookie_name = `your_cookie_name`

const encrypt  = (string)=> {
  if(typeof string === 'string'){
    return CryptoJS.AES.encrypt(string, my_secret_string).toString();
  }else{
    return CryptoJS.AES.encrypt(JSON.stringify(string), my_secret_string).toString(); 
  }
}

const decrypt =(hashkeys)=> {
  let bytes  = CryptoJS.AES.decrypt(hashkeys, my_secret_string);
  let res = bytes.toString(CryptoJS.enc.Utf8);
  return JSON.parse(res)?JSON.parse(res):res
}

export {
  encrypt,
  decrypt,
  cookie_name
}

//这里是

_app.js:

function MyApp(pageProps){
    ......
}

MyApp.getInitialProps = async (appContext ) => {
  let authenticated = false; 
  const cookies = nookies.get(appContext.ctx)
  const {router} = appContext
  // console.log(router.pathname)
 
  if(cookies[cookie_name]){
    const state = decrypt(cookies[cookie_name])
    authenticated = state.token?true:false 
  }else{
     
    if(router.pathname !== '/login'){
      //判断如果没有cookie,就跳转到login
      console.log(router.pathname, appContext.ctx.res)
      appContext.ctx.res.writeHead(302, {location: '/login'})
      appContext.ctx.res.end()
    }
  }
   

  const appProps = await App.getInitialProps(appContext);

  return { ...appProps, authenticated };
};
Comments are closed.