国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

django 用戶認(rèn)證系統(tǒng)

2019-11-08 19:31:40
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

django認(rèn)證系統(tǒng)包含三個(gè)部分:用戶、權(quán)限和分組

安裝

django項(xiàng)目默認(rèn)啟用了認(rèn)證系統(tǒng),如果不是使用django-admin.py創(chuàng)建項(xiàng)目的可以通過(guò)在settings配置文件里面的INSTALLED_APPS的列表里面添加django.contrib.auth和django.contrib.contenttypes這兩項(xiàng)然后運(yùn)行manage.py syncdb命令創(chuàng)建對(duì)應(yīng)的數(shù)據(jù)庫(kù)表即可

用戶Users

在Django-1.4.10/django/contrib/auth這個(gè)目錄下有一個(gè)model文件,里面有Permission,GroupManager,Group,UserManager,User,AnonymousUser這些類(lèi)的源碼,建議自己都去看一下,很多注釋?zhuān)瑢傩悦头椒纪ㄋ滓锥?,這里只點(diǎn)一下關(guān)鍵點(diǎn)

groups和user_permissions是是多對(duì)多的屬性,分別對(duì)應(yīng)到了類(lèi)Group和Permission

is_active這個(gè)屬性提醒我們不要輕易的刪掉一些對(duì)象,我們可以設(shè)置一個(gè)標(biāo)志位標(biāo)識(shí)該對(duì)象是否可用

set_unusable_passWord,標(biāo)識(shí)該用戶沒(méi)有密碼設(shè)置,注意不等同與空密碼

基本的用法

創(chuàng)建用戶

>>> from django.contrib.auth.models import User>>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')>>> user.save()

修改密碼,注意是使用set_password而不是password屬性

>>> from django.contrib.auth.models import User>>> u = User.objects.get(username__exact='john')>>> u.set_password('new password')>>> u.save()

創(chuàng)建超級(jí)用戶

manage.py createsuperuser --username=joe --email=joe@example.com

存儲(chǔ)用戶的額外信息

這是一個(gè)比較麻煩的事情,不過(guò)django還是提供了一個(gè)定制的方法

首先你要定義一個(gè)模型,在這個(gè)模型里面你可以定制額外的屬性或者方法,然后記得添加一個(gè)名為user的一對(duì)一的屬性名

復(fù)制代碼
from django.contrib.auth.models import Userclass UserPRofile(models.Model):    # 必選    user = models.OneToOneField(User)    # 自定義的屬性或者方法    accepted_eula = models.BooleanField()    favorite_animal = models.CharField(max_length=20, default="Dragons.")復(fù)制代碼

為了表明這個(gè)模型是對(duì)于那個(gè)給定的站點(diǎn),我們還需要配置一個(gè)AUTH_PROFILE_MODULE,這是一個(gè)字符串,包含兩部分信息,由點(diǎn)號(hào)相連

app名:大小寫(xiě)敏感,一般是你使用manage.py startapp創(chuàng)建時(shí)用的名稱(chēng)你自定義的模型名稱(chēng),大小寫(xiě)不敏感

比如,app名為accounts,模型名為UserProfile

AUTH_PROFILE_MODULE = 'accounts.UserProfile'

一旦一個(gè)用戶檔案模型(額外信息模型)被定義然后用上述方法指明,每一個(gè)user對(duì)象都會(huì)有一個(gè)方法--get_profile()--去返回跟該用戶相關(guān)的額外信息

然而,你必須注冊(cè)一個(gè)到django.db.models.signals.post_save信號(hào)的處理程序,并且在處理程序里面,如果created為真,才創(chuàng)建關(guān)聯(lián)的用戶額外信息

復(fù)制代碼
# in models.pyfrom django.contrib.auth.models import Userfrom django.db.models.signals import post_save# definition of UserProfile from above# ...def create_user_profile(sender, instance, created, **kwargs):    if created:        UserProfile.objects.create(user=instance)post_save.connect(create_user_profile, sender=User)復(fù)制代碼

把UserProfile添加到admin

復(fù)制代碼
from django.contrib import adminfrom django.contrib.auth.admin import UserAdminfrom django.contrib.auth.models import Userfrom my_user_profile_app.models import UserProfile# Define an inline admin descriptor for UserProfile model# which acts a bit like a singletonclass UserProfileInline(admin.StackedInline):    model = UserProfile    can_delete = False    verbose_name_plural = 'profile'# Define a new User adminclass UserAdmin(UserAdmin):    inlines = (UserProfileInline, )# Re-register UserAdminadmin.site.unregister(User)admin.site.register(User, UserAdmin)復(fù)制代碼

匿名用戶

我們來(lái)看一下匿名用戶的屬性,是對(duì)用戶的一個(gè)補(bǔ)充

復(fù)制代碼
class AnonymousUser(object):    id = None    username = ''    is_staff = False    is_active = False    is_superuser = False    _groups = EmptyManager()    _user_permissions = EmptyManager()復(fù)制代碼

web請(qǐng)求中的認(rèn)證

前面我們只是談到了操縱認(rèn)證相關(guān)對(duì)象的底層的APIs,在更高的層次,django可以把認(rèn)證框架鉤進(jìn)請(qǐng)求對(duì)象request系統(tǒng)中

首先,安裝會(huì)話中間件和認(rèn)證中間件(在MIDDLEWARE_CLASSES)里面添加sessionMiddleware和AuthenticationMiddleware,安裝好這兩個(gè)中間件后,你可以在視圖函數(shù)里面是用request.user(代表當(dāng)前已經(jīng)登陸的user對(duì)象,如果用戶還沒(méi)等,將代表一個(gè)匿名對(duì)象),可以使用is_authencated()方法來(lái)辨別是否已經(jīng)登陸

如何登陸用戶

django提供了兩個(gè)函數(shù)django.contrib.auth:authenticate()和login()

authentecate()

用給定的用戶名和密碼去認(rèn)證,返回一個(gè)User對(duì)象或者None

復(fù)制代碼
from django.contrib.auth import authenticateuser = authenticate(username='john', password='secret')if user is not None:    if user.is_active:        print "You provided a correct username and password!"    else:        print "Your account has been disabled!"else:    print "Your username and password were incorrect."復(fù)制代碼

login()

在視圖函數(shù)中可以使用login()方法去登陸一個(gè)用戶,這個(gè)方法需要一個(gè)HttpRequest對(duì)象和一個(gè)User對(duì)象,login()函數(shù)把用戶ID存在session里面(是用django的session框架,所以請(qǐng)確保啟用了會(huì)話中間件),如果是手工登陸用戶,請(qǐng)先條用authenticate()方法

復(fù)制代碼
from django.contrib.auth import authenticate, logindef my_view(request):    username = request.POST['username']    password = request.POST['password']    user = authenticate(username=username, password=password)    if user is not None:        if user.is_active:            login(request, user)            # Redirect to a success page.        else:            # Return a 'disabled account' error message    else:        # Return an 'invalid login' error message.復(fù)制代碼

如何注銷(xiāo)用戶

logout()

去注銷(xiāo)一個(gè)使用django.contrib.auth.login()方法登陸的用戶,請(qǐng)使用在視圖函數(shù)中使用django.contrib.auth.logout()方法注銷(xiāo),該方法需要一個(gè)HttpRequest對(duì)象并且沒(méi)有返回值

from django.contrib.auth import logoutdef logout_view(request):    logout(request)    # Redirect to a success page.

限制登陸用戶的訪問(wèn)

原始方法

在視圖函數(shù)中檢查request.user.is_authencated()是否為真,從而決定是重定向到一個(gè)登陸頁(yè)面或者是錯(cuò)誤頁(yè)面

login_required裝飾器

decorators.login_required([redirect_field_name=REDIRECT_FIELD_NAME,login_url=None])

作為一個(gè)快捷方式,可以直接使用login_required()裝飾器

from django.contrib.auth.decorators import login_required@login_requireddef my_view(request):

這個(gè)裝飾器按照以下步驟:

如果用戶沒(méi)有登陸,重定向到settings.LOGIN_URL(把在查詢(xún)字符串中的當(dāng)前絕對(duì)路徑傳參過(guò)去,例如/accounts/login/?next=/polls/3/如果用戶已經(jīng)登陸,正常執(zhí)行視圖函數(shù)

默認(rèn)情況下,用戶在成功認(rèn)證后的重定向路徑被存在查詢(xún)字符串中的next參數(shù)中,如果你想修改的話,請(qǐng)使用redirect_field_name參數(shù)@login_required(redirect_field_name='my_redirect_field')

注意的是,如果你提供了redirect_field_name,那么你很有可能需要去自定義登陸

內(nèi)建視圖函數(shù)

除了上面提到的login和logout,還有以下內(nèi)建的視圖函數(shù)

logout_then_login(request[,login_url]):注銷(xiāo)一個(gè)用戶然后重定向到一個(gè)登陸頁(yè)面

password_change(request[,template_name, post_change_redirect, password_change_form]):允許用戶修改他們的密碼

password_change_done(request[,template_name]):用戶修改密碼后的頁(yè)面

password_reset(request[,is_admin_site, template_name, email_template_name,password_reset_form,token_generator, post_reset_redirect, from_email]):通過(guò)生成的一個(gè)一次性的用來(lái)重置密碼的發(fā)往他們注冊(cè)郵箱的鏈接來(lái)允許用戶重置他們的密碼

password_reset_done(request[,template_name]):重置密碼后的頁(yè)面

password_reset_confirm(request[,uidb36, token, template_name, token_generator,set_password_form,post_reset_redirect]):展示一個(gè)用來(lái)輸入密碼的表單

redirect_to_login(next[,login_url, redirect_field_name]):重定向到一個(gè)登陸頁(yè)面然后在成功登陸后轉(zhuǎn)向另一個(gè)url

內(nèi)建表單

如果你不想使用上面的內(nèi)建視圖函數(shù),但是又不想自己寫(xiě)那些表單,你可以是用這些內(nèi)建的表單,這些內(nèi)建的表單都位于django.contrib.zuth.forms里面

classAdminPasswordChangeForm

A form used in the admin interface to change a user’s password.

classAuthenticationForm

A form for logging a user in.

classPasswordChangeForm?

A form for allowing a user to change their password.

classPasswordResetForm

A form for generating and emailing a one-time use link to reset a user’s password.

classSetPasswordForm

A form that lets a user change his/her password without entering the old password.

classUserChangeForm

A form used in the admin interface to change a user’s information and permissions.

classUserCreationForm

A form for creating a new user.

限制通過(guò)測(cè)試登陸的用戶的訪問(wèn)

有時(shí)候需要檢查用戶是否有某些權(quán)限,或者需要通過(guò)其他的測(cè)試等等才能訪問(wèn),比如下面的代碼:需要檢測(cè)用戶是否有投票的權(quán)限

def my_view(request):    if not request.user.has_perm('polls.can_vote'):        return HttpResponse("You can't vote in this poll.")

user_passes_test(func[,login_url=None]),你可以簡(jiǎn)單的使用user_passes_test

from django.contrib.auth.decorators import user_passes_test@user_passes_test(lambda u: u.has_perm('polls.can_vote'))def my_view(request):

如果你僅僅是想要檢測(cè)用戶是否有某項(xiàng)權(quán)限,你可以是用更簡(jiǎn)單的permission_required裝飾器,user_passes_test不會(huì)檢測(cè)用戶是否是匿名用戶,只是檢查是否能通過(guò)測(cè)試,這點(diǎn)是值得注意的,另外,如果用戶沒(méi)有通過(guò)測(cè)試,你可以定義login_url來(lái)重定向到一個(gè)登陸頁(yè)面,如:

@user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/')

permission_required裝飾器

permission_required([login_url=None,raise_exception=False]):檢查用戶是否具有特定的權(quán)限,可以自定義用戶不具有要求權(quán)限是重定向到登陸頁(yè)面,以及是否拋出異常等等

from django.contrib.auth.decorators import permission_required@permission_required('polls.can_vote', login_url='/loginpage/')def my_view(request):

權(quán)限

上面說(shuō)了很多關(guān)于權(quán)限的內(nèi)容,下面我們看看django的權(quán)限系統(tǒng)吧

django自帶一個(gè)簡(jiǎn)單的權(quán)限系統(tǒng) ,提供了給特定用戶和組用戶賦予權(quán)限的方法 ,在django的admin站點(diǎn)被使用,同時(shí)你也可以在自己的代碼中使用

默認(rèn)權(quán)限

當(dāng)django.contrib.auth被加入INSTALLED_APPS的時(shí)候,三項(xiàng)特別的權(quán)限--添加,修改和刪除--已經(jīng)為每個(gè)django模型創(chuàng)建好了,這三項(xiàng)權(quán)限是在你運(yùn)行manage.py syncdb的時(shí)候創(chuàng)建的

假設(shè)你有個(gè)應(yīng)用的app_label是foo,一個(gè)模型名為Bar,那么你可以這樣來(lái)測(cè)試這三個(gè)權(quán)限

add: user.has_perm('foo.add_bar')change: user.has_perm('foo.change_bar')delete: user.has_perm('foo.delete_bar')

自定義權(quán)限

如果要自定義權(quán)限的話,請(qǐng)使用permissions這個(gè)meta屬性,例如:

復(fù)制代碼
class Task(models.Model):    ...    class Meta:        permissions = (            ("view_task", "Can see available tasks"),            ("change_task_status", "Can change the status of tasks"),            ("close_task", "Can remove a task by setting its status as closed"),        )復(fù)制代碼

直接在程序中創(chuàng)建權(quán)限

復(fù)制代碼
from myapp.models import BlogPostfrom django.contrib.auth.models import Group, Permissionfrom django.contrib.contenttypes.models import ContentTypecontent_type = ContentType.objects.get_for_model(BlogPost)permission = Permission.objects.create(codename='can_publish',                                       name='Can Publish Posts',                                       content_type=content_type)復(fù)制代碼

這個(gè)方法與上面的方法相比,

權(quán)限API

直接看一下permission類(lèi)的源碼

class Permission(models.Model):    name = models.CharField(_('name'), max_length=50)    content_type = models.ForeignKey(ContentType)    codename = models.CharField(_('codename'), max_length=100)    objects = PermissionManager()

模板中的認(rèn)證數(shù)據(jù)

當(dāng)你使用RequestContent的時(shí)候,當(dāng)前已經(jīng)登陸的用戶和其權(quán)限在模板上下文中時(shí)可用的

Users

當(dāng)前已經(jīng)登陸的用戶(不管是否匿名),數(shù)據(jù)被存在模板變量{{user}}里面(前提是RequestContext被使用)

{% if user.is_authenticated %}    <p>Welcome, {{ user.username }}. Thanks for logging in.</p>{% else %}    <p>Welcome, new user. Please log in.</p>{% endif %}

Permissions

當(dāng)前已經(jīng)登陸的用戶的權(quán)限被存在模板變量{{perms}}里面

復(fù)制代碼
{% if perms.foo %}    <p>You have permission to do something in the foo app.</p>    {% if perms.foo.can_vote %}        <p>You can vote!</p>    {% endif %}    {% if perms.foo.can_drive %}        <p>You can drive!</p>    {% endif %}{% else %}    <p>You don't have permission to do anything in the foo app.</p>{% endif %}復(fù)制代碼

分組

看過(guò)了用戶和權(quán)限,我們繼續(xù)看分組吧

分組是最簡(jiǎn)單的歸類(lèi)的方法,分組之后你可以對(duì)組內(nèi)的用戶分配特定的權(quán)限或者其他label;當(dāng)然,一個(gè)用戶可以屬于多個(gè)組;一個(gè)組里面的用戶自動(dòng)獲取改分組擁有的權(quán)限

apis

我們直接看代碼吧,哈哈,就只有組名和對(duì)應(yīng)的權(quán)限兩項(xiàng)

class Group(models.Model):    name = models.CharField(_('name'), max_length=80, unique=True)    permissions = models.ManyToManyField(Permission,        verbose_name=_('permissions'), blank=True)    objects = GroupManager()

其他的認(rèn)證源

一般django自帶的認(rèn)證系統(tǒng)已經(jīng)滿足了大部分情況下的需求,但如果你有新的的需求的時(shí)候,你可以是用其他的認(rèn)證源

具體化認(rèn)證后端

django有一個(gè)檢查用戶名密碼的“認(rèn)證后端”的列表,django會(huì)從列表的第一項(xiàng)開(kāi)始嘗試,直到找到匹配的一項(xiàng)或者最后一項(xiàng)位置,你可以是用AUTHENTICATION_BACKENS設(shè)置你的認(rèn)證后端列表

自己寫(xiě)一個(gè)認(rèn)證后端

一個(gè)認(rèn)證后端是指一個(gè)實(shí)現(xiàn)了兩個(gè)必選方法和一系列可選權(quán)限相關(guān)的方法的類(lèi):get_user(user_id)和authenticate(**credentials)(get_group_permissions(),get_all_permissions(),has_perm(), andhas_module_perms()))

其中g(shù)et_user(user_id)中的user_id可以是用戶名,數(shù)據(jù)庫(kù)ID或者其他 ,返回一個(gè)用戶對(duì)象

authenticate把credentials的內(nèi)容作為關(guān)鍵字參數(shù) ,可能是這樣

class MyBackend(object):    def authenticate(self, username=None, password=None):        # Check the username/password and return a User.

或者是這樣

class MyBackend(object):    def authenticate(self, token=None):        # Check the token and return a User.

無(wú)論如何,authenticate都應(yīng)該驗(yàn)證credentials中的內(nèi)容,然后返回一個(gè)符合哪些驗(yàn)證條件的用戶對(duì)象,或者None

這是一個(gè)后端的例子

復(fù)制代碼
from django.conf import settingsfrom django.contrib.auth.models import User, check_passwordclass SettingsBackend(object):    """    Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD.    Use the login name, and a hash of the password. For example:    ADMIN_LOGIN = 'admin'    ADMIN_PASSWORD = 'sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de'    """    supports_inactive_user = False    def authenticate(self, username=None, password=None):        login_valid = (settings.ADMIN_LOGIN == username)        pwd_valid = check_password(password, settings.ADMIN_PASSWORD)        if login_valid and pwd_valid:            try:                user = User.objects.get(username=username)            except User.DoesNotExist:                # Create a new user. Note that we can set password                # to anything, because it won't be checked; the password                # from settings.py will.                user = User(username=username, password='get from settings.py')                user.is_staff = True                user.is_superuser = True                user.save()            return user        return None    def get_user(self, user_id):        try:            return User.objects.get(pk=user_id)        except User.DoesNotExist:            return None復(fù)制代碼

原文地址::http://www.cnblogs.com/qwj-sysu/p/4204423.html?utm_source=tuicool&utm_medium=referral


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 武平县| 镇江市| 溆浦县| 奇台县| 通道| 道孚县| 潍坊市| 禹州市| 平山县| 丰原市| 玉树县| 怀宁县| 永定县| 特克斯县| 吉木乃县| 宁远县| 南靖县| 密云县| 南雄市| 略阳县| 双城市| 亳州市| 双桥区| 宜川县| 调兵山市| 叙永县| 拉萨市| 陇南市| 军事| 丰台区| 桐城市| 正宁县| 阳东县| 洪湖市| 津南区| 南丰县| 临洮县| 河池市| 依兰县| 大方县| 洛浦县|