prisma orm_Prisma中的身份验证-第3部分:验证

news/2024/7/5 21:04:34

prisma orm

In Part 2 of this series we covered how to generate a temporary token for our user whenever they login or create an account. Now we’re going to wrap it up by restricting our data to only certain authorized users.

在本系列的第2部分中,我们介绍了如何在用户登录或创建帐户时为用户生成临时令牌。 现在,我们通过将数据限制为仅某些授权用户来进行包装。

获取我们的用户 (Getting our User)

When we create a token, we’re going to be giving it our user’s id and then use that id and jwt.verify to return data pertaining to that user if the verification was successful.

创建令牌时,如果验证成功,我们将为其提供用户ID,然后使用该ID和jwt.verify返回与该用户有关的数据。

The first step is to setup our context to handle the headers from the user’s request. If we change our context parameter to a function it will automatically have access to our request as an argument.

第一步是设置上下文,以处理来自用户请求的标头。 如果我们将context参数更改为函数,它将作为参数自动访问我们的请求。

file-name.js
文件名.js
const server = new GraphQLServer({
  typeDefs: './schema.graphql',
  resolvers,
  context(req) { return { prisma, req } }
});

Now we should be able to destructure the req object out of our context. If you try logging req you’ll see that there is a request.headers which will contain the authorization we passed into the GraphQL Playground. This is what we’ll give to jwt.verify with our secret to check if that user is valid. Since we’ll be doing this for every resolver we want to secure, let’s make it a function.

现在,我们应该能够从上下文中解构req对象。 如果您尝试记录req您将看到有一个request.headers ,其中将包含我们传递给GraphQL Playground的authorization 。 这就是我们将提供给jwt.verify的秘密信息,以检查该用户是否有效。 由于我们将对要保护的每个解析器执行此操作,因此,使其成为一个函数。

It’s pretty straightforward, we’re just getting our token from the header, removing Bearer so only the token is left, verify it, and return our user’s id.

这非常简单,我们只是从标头中获取令牌,删除Bearer ,只剩下令牌,验证令牌,然后返回用户的ID。

resolvers.js
resolvers.js
const getUser = req => {
  const authorization = req.request.headers.authorization;

  if (!authorization) throw new Error('Authentication Required');
  else {
    const token = authorization.replace('Bearer ', '');
    const user = jwt.verify(token, process.env.TOKEN_SECRET);

    return user.userId;
  }
};

架构图 (Schema)

Let’s add a few new resolvers into our schema first. We’re just going to practice with a currentUser query, deleteAccount and updateUser mutations, and a myAccount subscription.

首先让我们在架构中添加一些新的解析器。 我们只是一个练习currentUser查询, deleteAccountupdateUser突变,和myAccount订阅。

schema.graphql
schema.graphql
type Query {
  users: [User!]!
  currentUser: User!
}

type Mutation {
  createUser(data: CreateUserInput): User!
  loginUser(email: String!, password: String!): User!
  deleteAccount: User!
  updateUser(data: UpdateUserInput): User!
}

type Subscription {
  myAccount: AccountSubscription!
}

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

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

input UpdateUserInput {
  name: String 
  email: String
  password: String
}

enum MutationType {
  CREATED
  UPDATED 
  DELETED
}

type AccountSubscription {
  mutation: MutationType!
  node: User
}

查询 (Queries)

Authentication is now going to be incredibly simple, just get our user’s id with getUser and pass that to where. Now it will return data for the user that’s logged in and only that user.

身份验证现在变得非常简单,只需使用getUser获取我们的用户ID并将其传递给where 。 现在它将返回已登录用户的数据,并且仅返回该用户的数据。

resolvers.js
resolvers.js
const Query = {
  users(parent, args, { prisma }, info) { ... },
  currentUser(parent, args, { req, prisma }, info) {
    const userID = getUser(req);

    return prisma.query.user({ where: { id: userID } }, info);
  }
};

变异 (Mutations)

Mutations are just as easy, except with updates we’ll want to check if they’re changing their password first, since we’ll need to rehash it first.

变异同样容易,除了更新外,我们将要检查它们是否先更改了密码,因为我们需要先重新哈希它。

resolvers.js
resolvers.js
const Mutation = {
  async createUser(parent, { data }, { prisma }, info) { ... },
  async loginUser(parent, { email, password }, { prisma }, info) { ... },

  async deleteAccount(parent, args, { prisma, req }, info) {
    const userID = getUser(req);

    return prisma.mutation.deleteUser({ where: { id: userID } }, info);
  },
  async updateUser(parent, args, { prisma, req }, info) {
    const userID = getUser(req);

    if (typeof args.data.password === 'string') args.data.password = await bcrypt.hash(args.data.password, 10);

    return prisma.mutation.updateUser({
      where: { id: userID },
      data: args.data
    }, info);
  },
};

订阅内容 (Subscriptions)

Subscriptions are just as self-explanatory once again, just remember to add Subscription to your resolvers in index.js.

订阅再次是不言自明的,只记得在index.js中将Subscription添加到您的解析器中。

resolvers.js
resolvers.js
const Subscription = {
  myAccount: {
    subscribe(parent, args, { prisma, req }, info) {
      const userID = getUser(req);

      return prisma.subscription.user({ where: { node: { id: userID } } }, info);
    }
  }
}

总结思想 (Closing Thoughts)

That may have seemed like a lot of work, but actually using authentication is by far the easiest part of the process. The important thing is to understand how it works even though you’ll most likely be utilizing a starter boilerplate for most of your real projects.

这似乎是一项艰巨的工作,但实际上使用身份验证是该过程中最容易的部分。 重要的是要了解它是如何工作的,即使您很可能在大多数实际项目中都使用入门样板。

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

prisma orm


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

相关文章

H5前端基础——盒子模型

CSS中将每一个元素都设置为了一个矩形的盒子 将所有的元素都设置为盒子,是为了方便页面的布局 当这些元素都是盒子以后,我们的布局就变成了在页面中摆放盒子 盒子模型 每个盒子都由如下几部分构成 内容区 内容区相当于盒子存放东西的空间 内容区在盒子的…

H5前端基础——布局

浮动 使用float来设置元素浮动 可选值 none 默认值,不浮动,元素在文档流中 left 元素向左浮动 right 元素向右浮动 特点 1.元素浮动以后会完全脱离文档流 2.浮动以后元素会一直向父元素的最上方移动 3.直到遇到父元素的边框或者其他的浮动元素&#x…

盖茨比乔布斯_使用盖茨比的useStaticQuery挂钩的快速指南

盖茨比乔布斯The useStaticQuery React Hook was added to Gatsby.js starting with version 2.1.0, and it’s an incredibly convenient way to make (build-time) GraphQL queries from any component within a Gatsby site. In this quick lesson, we’ll go over how to i…

客户端封装Fragment和Activity

一、封装activity public abstract class Activity extends AppCompatActivity {Overrideprotected void onCreate(Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);initWindows();if (initargs(getIntent().getExtras())) {// 得到界面Id并设置到Ac…

Android Studio中的手机通讯录开发

Android Studio中的手机通讯录,包含功能(按首字母排序,动态添加) 第一次写博客,也刚踏入工作,想着把自己在项目中遇到的问题,以及自己在工作中所做的项目记录下来,方便以后自己查找…

redis排序_如何在Redis中管理排序集

redis排序介绍 (Introduction) Redis is an open-source, in-memory key-value data store. In Redis, sorted sets are a data type similar to sets in that both are non repeating groups of strings. The difference is that each member of a sorted set is associated w…

Android版本和API Level的对应关系

在开发Android时,老是不知道Android版本号和对应API level,这个问题真是麻烦,我们在发布声波传输SDK时也遇到这样的问题,版本号是对外发布的版本号,一般都是主版本号.子版本号.修正版本号的命名规则,说白了…

[dotNET]使用HttpWebRequest请求远端服务器时如何加载SSL证书

使用HttpWebRequest请求远端服务器时如何加载SSL证书编写者:郑昀UltraPower首先加上引用“System.Security.DLL”,其次在工程中using System.Security.Cryptography.X509Certificates;这样就可以使用“X509Certificate Class”了,它的定义参见…