fullstack GraphQL学习笔记(13)认证

1、django内置了用户的管理

在hackersnews下创建一个users文件夹并在该文件夹下创建一个schema.py

from django.contrib.auth import get_user_model

import graphene
from graphene_django import DjangoObjectType


class UserType(DjangoObjectType):
    class Meta:
        model = get_user_model()


class CreateUser(graphene.Mutation):
    user = graphene.Field(UserType)

    class Arguments:
        username = graphene.String(required=True)
        password = graphene.String(required=True)
        email = graphene.String(required=True)

    def mutate(self, info, username, password, email):
        user = get_user_model()(
            username=username,
            email=email,
        )
        user.set_password(password)
        user.save()

        return CreateUser(user=user)


class Mutation(graphene.ObjectType):
    create_user = CreateUser.Field()

  这里可以看到我们并没有像createLink那样把所有的字段列出来,而是使用了user = graphene.Field(UserType),以返回整个user.

在settings.py中注册app users

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'graphene_django',
    'links',
    'users',
]

  

下面把User的schema放在根schema下

import graphene
import links.schema
import users.schema


class Query(links.schema.Query, graphene.ObjectType):
    pass

class Mutation(users.schema.Mutation,links.schema.Mutation, graphene.ObjectType):
    pass


schema = graphene.Schema(query=Query,mutation=Mutation)

  现在我们可以执行mutation操作了。

mutation{
  createUser(
    username:"adcers",
    password:"123345ddd",
    email:"adcers@124.com"
  ){
    user{
      username
      email
    }
  }
}

  下面创建查询用户,在user/schema.py

class Query(graphene.ObjectType):
    users = graphene.List(UserType)

    def resolve_users(self, info):
        return get_user_model().objects.all()

  在hackernews/schema.py增加

class Query(users.schema.Query, links.schema.Query, graphene.ObjectType):
    pass

  这样我们便可以查询了

query{
  users{
    id
    username
    email
  }
}

  2、用户认证

django内置了用户认证的内容,使用session在服务端保存临时数据,是一种有状态的服务。今天多数的服务都是无状态的,即一次请求没有任何依赖。我们将使用django-graphql-jwt在Graphene中实现JWT令牌当用户注册或登录时,将返回令牌:识别用户身份的一段数据。用户以后再次访问需要认证的站点时必须把token放在http头部以便于验证。遗憾的是,我们之前使用的GraphiQL Web界面不接受添加自定义HTTP标头。从现在开始,我们将使用Insomnia桌面应用程序。您可以在此处下载并安装它。

配置django-graphql-jwt

在settings.py的中间件中增加

'graphql_jwt.middleware.JSONWebTokenMiddleware',

  另外在settings.py中新增设置:

AUTHENTICATION_BACKENDS = [
    'graphql_jwt.backends.JSONWebTokenBackend',
    'django.contrib.auth.backends.ModelBackend',
]

  在hackernews中使用该库,修改Mutation

import graphql_jwt

class Mutation(users.schema.Mutation,links.schema.Mutation, graphene.ObjectType):
    token_auth = graphql_jwt.ObtainJSONWebToken.Field()
    verify_token = graphql_jwt.Verify.Field()
    refresh_token = graphql_jwt.Refresh.Field()

  该库为我们创建了三个Mutaitions:

token_auth:接受用户名和密码,生成token

verfiy:接受token作为参数,验证token是否有效

refresh:在令牌未过期的更新到期时间内获取新令牌(如果它们已启用到期).

除此之外,可以在库上配置Mutations和JWT的各个方面.请查看文档以获取更多信息。

mutation{
  tokenAuth(
    username:"22323"
    password:"adfasdfa"
  ){
    token
  }
}

  返回结果:

{
  "data": {
    "tokenAuth": {
      "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImxpdHVmdSIsImV4cCI6MTUzNTUxNDAxNSwib3JpZ19pYXQiOjE1MzU1MTM3MTV9.7AawmYv4F4OjYCPswpjrPDt_phf4BhZNFtvkuTxVfp8"
    }
  }
}

  验证token

mutation{
  verifyToken(token:"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImxpdHVmdSIsImV4cCI6MTUzNTUxNDAxNSwib3JpZ19pYXQiOjE1MzU1MTM3MTV9.7AawmYv4F4OjYCPswpjrPDt_phf4BhZNFtvkuTxVfp8"){
    payload
  }
}

  返回结果:

{
  "data": {
    "verifyToken": {
      "payload": {
        "username": "22323", "exp": 1535514015, "orig_iat": 1535513715 } } } }

 测试身份验证

为了测试我们的身份验证是否正常工作,让我们创建一个名为Query的查询me,如果登录则应该返回用户的信息,否则返回错误。

修改users/schema.py

class Query(graphene.ObjectType):
    users = graphene.List(UserType)
    me = graphene.Field(UserType)

    def resolve_users(self, info):
        return get_user_model().objects.all()

    def resolve_me(self, info):
        user = info.context.user
        if user.is_anonymous:
            raise Exception('Not logged!')

        return user

  为了测试它,我们需要使用tokenAuth Mutation 获取一个token,并在HTTP头部设置AUTHORIZATION:使用前缀JWT+token现在,我们要去Inmsonia客户端:

query{
	me{
		id
		username
	}
}

  便可以查询到需要的信息。

 

posted @ 2018-08-29 11:50  tutu_python  阅读(377)  评论(0)    收藏  举报