Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Init version for auth api #1

Open
wants to merge 1 commit into
base: api_auth
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions 3rdlib/jwt_auth/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Compiled python modules.
*.pyc

# Setuptools distribution folder.
/dist/

# Python egg metadata, regenerated from source files by setuptools.
/*.egg-info
1 change: 1 addition & 0 deletions 3rdlib/jwt_auth/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include README.rst
6 changes: 6 additions & 0 deletions 3rdlib/jwt_auth/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
jwt_auth
--------

To use (with caution), simply do::
jwt_auth
API
Empty file.
71 changes: 71 additions & 0 deletions 3rdlib/jwt_auth/jwt_auth/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# coding: utf-8


from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField

from .models import Staff


class StaffCreationForm(forms.ModelForm):
password1 = forms.CharField(widget=forms.PasswordInput)
password2 = forms.CharField(widget=forms.PasswordInput)

class Meta:
model = Staff
fields = ('email', 'realname')

def clean_password2(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password2 and password1 != password2:
raise forms.ValidationError('密码不正确')
return password2

def save(self, commit=True):
staff = super(StaffCreationForm, self).save(commit=False)
staff.set_password(self.cleaned_data['password1'])
if commit:
staff.save()
return staff


class StaffChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField()

class Meta:
model = Staff
fields = ('email', 'password', 'realname')

def clean_password(self):
return self.initial['password']


class StaffAdmin(BaseUserAdmin):
form = StaffChangeForm
add_form = StaffCreationForm

list_display = ('email', 'is_admin')
list_filter = ('is_admin',)
fieldsets = (
(None, {'fields': ('email', 'realname', 'password')}),
('Personal info', {'fields': ('last_login',)}),
('Permissions', {'fields': ('is_admin',)}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'last_login', 'password1', 'password2')}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()


# Now register the new UserAdmin
admin.site.register(Staff, StaffAdmin)
admin.site.unregister(Group)
5 changes: 5 additions & 0 deletions 3rdlib/jwt_auth/jwt_auth/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class JwtAuthConfig(AppConfig):
name = 'jwt_auth'
115 changes: 115 additions & 0 deletions 3rdlib/jwt_auth/jwt_auth/backends.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import jwt
from django.conf import settings
from rest_framework import authentication, exceptions
from .models import Staff


class JWTAuthentication(authentication.BaseAuthentication):
authentication_header_prefix = 'Token'

def authenticate(self, request):
"""
The `authenticate` method is called on every request regardless of
whether the endpoint requires authentication.

`authenticate` has two possible return values:

1) `None` - We return `None` if we do not wish to authenticate. Usually
this means we know authentication will fail. An example of
this is when the request does not include a token in the
headers.

2) `(user, token)` - We return a user/token combination when
authentication is successful.

If neither case is met, that means there's an error
and we do not return anything.
We simple raise the `AuthenticationFailed`
exception and let Django REST Framework
handle the rest.
"""
request.user = None

# `auth_header` should be an array with two elements: 1) the name of
# the authentication header (in this case, "Token") and 2) the JWT
# that we should authenticate against.
auth_header = authentication.get_authorization_header(request).split()
auth_header_prefix = self.authentication_header_prefix.lower()

if not auth_header:
return None

if len(auth_header) == 1:
# Invalid token header. No credentials provided. Do not attempt to
# authenticate.
return None

elif len(auth_header) > 2:
# Invalid token header. The Token string should not contain spaces. Do
# not attempt to authenticate.
return None

# The JWT library we're using can't handle the `byte` type, which is
# commonly used by standard libraries in Python 3. To get around this,
# we simply have to decode `prefix` and `token`. This does not make for
# clean code, but it is a good decision because we would get an error
# if we didn't decode these values.
prefix = auth_header[0].decode('utf-8')
token = auth_header[1].decode('utf-8')

if prefix.lower() != auth_header_prefix:
# The auth header prefix is not what we expected. Do not attempt to
# authenticate.
return None

# By now, we are sure there is a *chance* that authentication will
# succeed. We delegate the actual credentials authentication to the
# method below.
return self._authenticate_credentials(request, token)

def _authenticate_credentials(self, request, token):
"""
Try to authenticate the given credentials. If authentication is
successful, return the user and token. If not, throw an error.
"""
try:
payload = jwt.decode(token, settings.SECRET_KEY)
except:
msg = 'Invalid authentication. Could not decode token.'
raise exceptions.AuthenticationFailed(msg)

try:
staff = Staff.objects.get(pk=payload['id'])
except Staff.DoesNotExist:
msg = 'No staff matching this token was found.'
raise exceptions.AuthenticationFailed(msg)

if not staff.is_active:
msg = 'This user has been deactivated.'
raise exceptions.AuthenticationFailed(msg)

return (staff, token)


class EmailOrMobileAuthBackend(object):
def authenticate(self, email=None, password=None):
try:
user = Staff.objects.get(email=email)
if user.check_password(password):
return user
except Staff.DoesNotExist:
if email.isdigit():
try:
user = Staff.objects.get(mobile=email)
if user.check_password(password):
return user
except Staff.DoesNotExist:
return None
else:
return None

def get_user(self, user_id):
try:
return Staff.objects.get(pk=user_id)
except Staff.DoesNotExist:
return None
29 changes: 29 additions & 0 deletions 3rdlib/jwt_auth/jwt_auth/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.8 on 2017-12-13 07:30
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='Staff',
fields=[
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('email', models.EmailField(max_length=255, primary_key=True, serialize=False, unique=True)),
('is_active', models.BooleanField(default=True)),
('is_admin', models.BooleanField(default=False)),
],
options={
'abstract': False,
},
),
]
20 changes: 20 additions & 0 deletions 3rdlib/jwt_auth/jwt_auth/migrations/0002_staff_username.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.8 on 2017-12-13 08:33
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('jwt_auth', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='staff',
name='username',
field=models.CharField(default='', max_length=24, verbose_name='用户名'),
),
]
20 changes: 20 additions & 0 deletions 3rdlib/jwt_auth/jwt_auth/migrations/0003_auto_20171213_0850.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.8 on 2017-12-13 08:50
from __future__ import unicode_literals

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('jwt_auth', '0002_staff_username'),
]

operations = [
migrations.RenameField(
model_name='staff',
old_name='username',
new_name='realname',
),
]
Empty file.
70 changes: 70 additions & 0 deletions 3rdlib/jwt_auth/jwt_auth/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# coding: utf-8
from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
from django.utils import timezone

class StaffManager(BaseUserManager):

def create_staff(self, email, password, **kwargs):
if not email:
raise '邮箱地址不能为空'
if not password:
raise ValueError('密码不合法.')

if not password == kwargs.get('confirm_password'):
raise ValueError('请确认你的密码.')

staff = self.model(email=self.normalize_email(email), last_login=timezone.now())
staff.set_password(password)
staff.save(using=self._db)
return staff


def create_superuser(self, email, password):
staff = self.create_staff(email, password)
staff.is_admin = True
staff.save(using=self._db)
return staff


class Staff(AbstractBaseUser):
realname = models.CharField(u"用户名", max_length=24, default="")
email = models.EmailField(primary_key=True, max_length=255, unique=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = StaffManager()

USERNAME_FIELD = 'email'

def is_staff(self):
return self.is_admin

def __str__(self):
return self.email


def has_module_perms(self, demo):
return True


def has_perm(self, perm, obj=None):
return True


def get_short_name(self):
# The user is identified by their email address
return self.email


def get_full_name(self):
# The user is identified by their email address
return self.email

@property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin

def get_username(self):
return self.email
Loading