prisma orm_Prisma中的身份验证-第2部分:JSON Web令牌和登录

news/2024/7/4 23:03:38

prisma orm

Over in Part 1 we setup our project to require authentication to interact with the GraphQL API. Now, we’re going to look at logging in users and generating JSON Web Tokens (JWT) for our users to lock them out from data we don’t want them to access.

在第1部分中,我们设置了项目以要求进行身份验证才能与GraphQL API交互。 现在,我们将研究登录用户并为用户生成JSON Web令牌(JWT),以将其锁定在我们不希望他们访问的数据中。

安装 (Installation)

We’re going to be using bcrypt to encrypt our passwords, since storing passwords as just normal strings is very bad for security, and jsonwebtoken to generate tokens we can use to verify if a user should have access to something.

我们将使用bcrypt来加密密码,因为仅将密码存储为普通字符串对安全性非常不利,而使用jsonwebtoken生成令牌则可以用来验证用户是否应该访问某些内容。

$ npm install bcryptjs jsonwebtoken

加密 (Encryption)

Let’s take a moment to go over the two libraries we’ll be using. If you’re already familiar with them then you can skip this as well as the next section.

让我们花点时间浏览一下我们将要使用的两个库。 如果您已经熟悉它们,则可以跳过本节以及下一节。

bcrypt allows us to encrypt our passwords and compare that hashed version with another string to see if they’re the same. The point of this is that you can compare the hashed and un-hashed versions but you can never decode the original from it. This way, even if someone were to query for a users password, although they would get something, it wouldn’t be usable to break into anyone’s account.

bcrypt允许我们加密密码,并将该哈希版本与另一个字符串进行比较,以查看它们是否相同。 这样做的目的是,您可以比较散列和未散列的版本,但永远无法从中解码原始版本。 这样,即使有人要查询用户密码,尽管他们会得到一些东西,但闯入任何人的帐户将不可行。

It’s pretty simple, it just takes the string we would like to hash, and the number of salts. A salt is just a cycle that it runs the password through its hashing algorithm, the higher the number the more secure it’ll be but the longer it’ll take to generate.

这很简单,只需要我们想要哈希的字符串和盐的数量。 盐只是通过哈希算法运行密码的一个周期,数字越高,安全性越高,但生成时间就越长。

import bcrypt from 'bcryptjs';

const password = 'pleaseDontHackMe3248';
console.log('Raw Password: ', password);

bcrypt.hash(password, 8)
  .then(hashed => {
    console.log('Secure Password: ', hashed);

    // Must take the string version then the hashed version
    const doesMatch = bcrypt.compare(password, hashed);

    return doesMatch;
  }
  ).then(doesMatch => console.log('Password Matches: ', doesMatch));

生成令牌 (Generating Tokens)

jsonwebtoken is an extremely popular library for generating unique access tokens that we can use to verify for authenticity and even have expire over some period of time.

jsonwebtoken是一个非常流行的库,用于生成唯一的访问令牌,我们可以使用该令牌来验证其真实性,甚至可以在一段时间内过期。

jwt.sign takes in something to link the token to a particular user and a secret that we’ll use to verify if the token is valid, since anyone could generate their own outside of our app. We can set the expiration with the expiresIn property and a string describing the time span, such as 5000 (milliseconds), '8d', or '9 months'.

jwt.sign接受了一些将令牌链接到特定用户的东西,以及一个我们将用来验证令牌是否有效的秘密,因为任何人都可以在我们的应用程序外部生成自己的密码。 我们可以使用expiresIn属性和描述时间跨度的字符串(例如5000 (毫秒), '8d''9 months' )来设置到期时间。

const token = jwt.sign({ name: 'Someone' }, 'anotherSecret', { expiresIn: '1 day' });
console.log(token);

Now we can use jwt.verify to use our secret to decrypt our user’s data that was stored. You’d normally be storing this secret as an environment variable of course.

现在,我们可以使用jwt.verify来使用我们的机密来解密存储的用户数据。 通常,您通常会将此秘密存储为环境变量。

const decrypted = jwt.verify(token, 'anotherSecret');
console.log(decrypted);

创建一个用户 (Creating a User)

Creating a login system is a very simple process. All we need to do is give every user a token when they run the login or createUser mutations, which would normally be saved and sent back from the client side, but we’ll stick with GraphQL Playground’s header for now.

创建登录系统是一个非常简单的过程。 我们需要做的就是在每个用户运行logincreateUser突变时为他们提供一个令牌,这些令牌通常会保存并从客户端发送回去,但是现在我们将继续使用GraphQL Playground的标头。

Let’s start with adding some mutations and generating a token for our user. Since a user will only sometimes need a token, we can leave it nullable.

让我们开始添加一些变异并为我们的用户生成令牌。 由于用户有时仅需要令牌,因此我们可以将其保留为空。

schema.graphql
schema.graphql
type Mutation {
  createUser(data: CreateUserInput): User!
  loginUser(email: String!, password: String!): User!
}

type User {
  id: ID!
  name: String!
  email: String!
  password: String! 
  token: String
}

input CreateUserInput {
  name: String! 
  email: String!
  password: String!
}

With our schema in place, let’s try to create a new user with a valid token.

使用我们的架构后,让我们尝试使用有效令牌创建一个新用户。

resolvers.
解析器。
const expiresIn = '1 day'; // We'll be using this value repeatedly.

const Mutation = {
  async createUser(parent, { data }, { prisma }, info) {
    const password = await bcrypt.hash(data.password, 10);
    const user = await prisma.mutation.createUser({
      data: {
        ...data,
        password
      }
    });
    // Since id is added by prisma it is unavailable when creating a user.
    const userWithToken = {
      ...user,
      token: jwt.sign({ userId: user.id }, process.env.TOKEN_SECRET, { expiresIn })
    };

    return userWithToken;
  }
}

Finally, just add our secret to our environment variables, which by now, should look like this.

最后,只需将我们的秘密添加到我们的环境变量中,到现在,它应该看起来像这样。

.env
.env
API_SECRET=SuperSecretSecret
TOKEN_SECRET=EvenSecreterSecret

登录用户 (Logging in a User)

The last step for now is to use the user’s email to get their account and compare their encoded password with the one they entered. If it’s correct, then we’ll generate and return a new token for them.

现在的最后一步是使用用户的电子邮件获取他们的帐户,并将他们的编码密码与他们输入的密码进行比较。 如果正确的话,我们将为其生成并返回一个新令牌。

resolvers.js
resolvers.js
const expiresIn = '1 day';

const Mutation = {
  async createUser(parent, { data }, { prisma }, info) {...},
  async loginUser(parent, { email, password }, { prisma }, info) {
    const user = await prisma.query.user({ where: { email } });
    if (!user) throw new Error('No User Found');

    const isValid = await bcrypt.compare(password, user.password);
    if (!isValid) throw new Error('Wrong Password');

    const userWithToken = {
      ...user,
      token: jwt.sign({ userId: user.id }, process.env.TOKEN_SECRET, { expiresIn })
    }

    return userWithToken
  }
}

Stay tuned for part 3, where I’ll cover validation for queries, mutations and subscriptions!

请继续关注第3部分,其中将介绍查询,突变和订阅的验证!

翻译自: https://www.digitalocean.com/community/tutorials/graphql-prisma-authentication-tokens-login

prisma orm


http://www.niftyadmin.cn/n/3649328.html

相关文章

“微笑涛声”微信公众号正式上线运行

2020年2月2日,微笑涛声个人博客上线,经过一年多的更新,写了原创文章125篇,访问达到8万次以上,百度收录500,自己也成长了许多。 ▣ 博主主站地址:微笑涛声 【www.cztcms.cn】 ▣ 博主其他平台&a…

angular 模块构建_使用传单在Angular中构建地图,第4部分:形状服务

angular 模块构建By now, we’ve built a Leaflet map in Angular and we are able to render markers and pop-ups. Let’s now render shapes for the different US states. 到目前为止 ,我们已经在Angular中构建了Leaflet地图 ,并且能够渲染标记和弹出…

[收藏]Web Service故障处理[Matt PowellScott Seely]

Web Service故障处理 2001-10-17 Matt Powell and Scott Seelyyesky  概述:这篇文章主要给出了一些常规的Web Service 的故障处理技巧,并辅以Favorites Service为例进行说明。  简介  Web Service 的故障处理会是一件很困难的事情,因为…

Android框架之TableLayout的使用

1.简介 我们在应用viewpager的时候,经常会使用TabPageIndicator来与其配合。达到很漂亮的效果。但是TabPageIndicator是第三方的,而且比较老了,当然了现在很多大神都已经开始自己写TabPageIndicator来满足自己的需求,在2015年的go…

可视化大屏项目:学生就业统计展示

最近在学习前端开发,顺便做了一个项目,学生就业统计展示,可以直观的看到学生就业数据统计。由静态数据提供展示,使用Css3Html5JavaScript进行开发。源代码可以到文章底部扫码进行购买。 最终显示效果如下 购买链接:可视…

嵌入storybook组件_如何使用Storybook构建JS组件

嵌入storybook组件介绍 (Introduction) Storybook is an open source tool for developing UI (user interface) components in isolation and it integrates pretty well with most front end frameworks including React, Vue, and Angular and others. It makes building UI…

JSON解析之手动解析

1、JSON简介 1)概念: JSON的全称是JavaScript Object Notation,是一种轻量级的数据交换格式。 2)特点: (1)本质就是具有特定格式的字符串 (2)JSON完全独立于编程语言 &am…

leaflet弹窗_使用Leaflet在Angular中构建地图,第3部分:弹出服务

leaflet弹窗In my last post, we expanded upon our Angular Leaflet project by creating a service to serve up Markers. We’re going to now do the same thing for popups. 在上一篇文章中 ,我们通过创建服务标记的服务扩展了Angular Leaflet项目。 现在&…