django認(rèn)證系統(tǒng)實(shí)現(xiàn)自定義權(quán)限管理的方法
本文記錄使用django自帶的認(rèn)證系統(tǒng)實(shí)現(xiàn)自定義的權(quán)限管理系統(tǒng),包含組權(quán)限、用戶權(quán)限等實(shí)現(xiàn)。
0x01. django認(rèn)證系統(tǒng)
django自帶的認(rèn)證系統(tǒng)能夠很好的實(shí)現(xiàn)如登錄、登出、創(chuàng)建用戶、創(chuàng)建超級(jí)用戶、修改密碼等復(fù)雜操作,并且實(shí)現(xiàn)了用戶組、組權(quán)限、用戶權(quán)限等復(fù)雜結(jié)構(gòu),使用自帶的認(rèn)證系統(tǒng)就能幫助我們實(shí)現(xiàn)自定義的權(quán)限系統(tǒng)達(dá)到權(quán)限控制的目的。
0x02. 認(rèn)證系統(tǒng)User對(duì)象
User對(duì)象顧名思義即為表示用戶的對(duì)象,里面的屬性包括:
username password email first_name last_name is_superuser is_active
創(chuàng)建好對(duì)象后,django會(huì)自動(dòng)生成表,表名為auth_user,包含以上字段。具體的api文檔如下所示:
class models.User User 對(duì)象具有如下字段: username 必選。少于等于30個(gè)字符。 用戶名可以包含字母、數(shù)字、_、@、+、.和- 字符。 first_name 可選。 少于等于30個(gè)字符。 last_name 可選。少于30個(gè)字符。 email 可選。郵箱地址。 password 必選。 密碼的哈希及元數(shù)據(jù)。(Django 不保存原始密碼)。原始密碼可以無限長(zhǎng)而且可以包含任意字符。參見密碼相關(guān)的文檔。 groups 與Group 之間的多對(duì)多關(guān)系。 user_permissions 與Permission 之間的多對(duì)多關(guān)系。 is_staff 布爾值。指示用戶是否可以訪問Admin 站點(diǎn)。 is_active 布爾值。指示用戶的賬號(hào)是否激活。 is_superuser 布爾值。只是這個(gè)用戶擁有所有的權(quán)限而不需要給他們分配明確的權(quán)限。 last_login 用戶最后一次登錄的時(shí)間。 date_joined 賬戶創(chuàng)建的時(shí)間。當(dāng)賬號(hào)創(chuàng)建時(shí),默認(rèn)設(shè)置為當(dāng)前的date/time。
一般在注冊(cè)操作中會(huì)用到該方法,實(shí)現(xiàn)注冊(cè)一個(gè)用戶,用到的函數(shù)是User.objects.create_user(),在新建用戶的時(shí)候需要判斷用戶是否存在,我的實(shí)現(xiàn)方式是,User.objects.get(username=xxx)去獲取一個(gè)用戶User對(duì)象,用try except實(shí)現(xiàn),如果用戶不存在則拋出User.DoesNotExist異常,在這個(gè)異常中進(jìn)行創(chuàng)建用戶的操作。具體代碼如下:
# 注冊(cè)操作 from django.contrib.auth.models import User try: User.objects.get(username=username) data = {'code': '-7', 'info': u'用戶已存在'} except User.DoesNotExist: user = User.objects.create_user(username, email, password) if user is not None: user.is_active = False user.save()
該過程中密碼字段會(huì)自動(dòng)加密存儲(chǔ)。無需關(guān)注過多細(xì)節(jié)。
0x03. 登錄登出用戶
創(chuàng)建好用戶后,就是登錄及登出了,django認(rèn)證系統(tǒng)提供了login()及l(fā)ogout()函數(shù),能夠自動(dòng)登錄登出,并且修改session值,非常方便。驗(yàn)證用戶身份使用authenticate函數(shù)能自動(dòng)進(jìn)行password字段的hash比對(duì)。
具體實(shí)現(xiàn)代碼如下:
from django.contrib.auth import authenticate, login, logout # 認(rèn)證操作 ca = Captcha(request) if ca.validate(captcha_code): user = authenticate(username=username, password=password) if user is not None: if user.is_active: # 登錄成功 login(request, user) # 登錄用戶 data = {'code': '1', 'info': u'登錄成功', 'url': 'index'} else: data = {'code': '-5', 'info': u'用戶未激活'} else: data = {'code': '-4', 'info': u'用戶名或密碼錯(cuò)誤'} else: data = {'code': '-6', 'info': u'驗(yàn)證碼錯(cuò)誤'}
登出操作如下:
from django.contrib.auth import authenticate, login, logout def logout_system(request): """ 退出登錄 :param request: :return: """ logout(request) return HttpResponseRedirect('/')
0x04. login_required裝飾器
通過該裝飾器能夠使視圖函數(shù)首先判斷用戶是否登錄,如果未登錄會(huì)跳到默認(rèn)在settings.py設(shè)置的LOGIN_URL參數(shù)對(duì)應(yīng)的url,如:LOGIN_URL = '/'。使用方法如下所示:
from django.contrib.auth.decorators import login_required @login_required def user_index(request): """ 用戶管理首頁(yè) :param request: :return: """ if request.method == "GET": # 用戶視圖實(shí)現(xiàn)
0x05. 用戶組及權(quán)限分配
組對(duì)象包含的字段只有name,但是外鍵了幾張表,能夠與user、permissions,產(chǎn)生多對(duì)多的關(guān)系,我在自定義權(quán)限實(shí)現(xiàn)中,采用的是權(quán)限寫死的方法,添加用戶組權(quán)限。
創(chuàng)建組的函數(shù)采用Group.objects.create(name=xxx),就能實(shí)現(xiàn)了。當(dāng)然也跟創(chuàng)建用戶一樣,需要先判斷是否組名已經(jīng)存在。
創(chuàng)建好組名后,下一步就需要為每個(gè)組分配權(quán)限了,從前端提交過來的權(quán)限列表,然后后端采用groups.permissions.add(permission)的方式依次將權(quán)限添加進(jìn)組。
添加完組權(quán)限后,最后一步是將組名添加進(jìn)用戶屬性,區(qū)分用戶屬于哪個(gè)組。
具體實(shí)現(xiàn)代碼如下:
# 創(chuàng)建組 try: Group.objects.get(name=role_name) data = {'code': -7, 'info': u'組名已存在'} except Group.DoesNotExist: groups = Group.objects.create(name=role_name) if log_manage == 'true': permission = Permission.objects.get(codename='access_log') groups.permissions.add(permission) if role_manage == 'true': permission = Permission.objects.get(codename='access_role_manage') groups.permissions.add(permission) if user_manage == 'true': permission = Permission.objects.get(codename='access_user_manage') groups.permissions.add(permission) if get_users is not None: for user in get_users: # 每個(gè)user添加組屬性 db_user = get_object_or_404(User, username=user) db_user.groups.add(groups) data = {'code': 1, 'info': u'添加成功'} return HttpResponse(json.dumps(data))
0x06. 權(quán)限模型及權(quán)限控制
在上一點(diǎn)中用到的Permission.objects.get(codename='access_user_manage')是通過權(quán)限模型創(chuàng)建,需要在models中創(chuàng)建一個(gè)權(quán)限類,然后在meta中進(jìn)行定義codename。
class AccessControl(models.Model): """ 自定義權(quán)限控制 """ class Meta: permissions = ( ('access_dashboard', u'控制面板'), ('access_log', u'日志管理'), ('access_role_manage', u'角色管理'), ('access_user_manage', u'用戶管理'), )
運(yùn)行后,會(huì)自動(dòng)在數(shù)據(jù)庫(kù)中創(chuàng)建相應(yīng)的表,并且插入數(shù)據(jù)。
在創(chuàng)建好權(quán)限之后,下一步就是在各個(gè)視圖中插入權(quán)限控制代碼了。permission_required(),參數(shù)為當(dāng)前應(yīng)用名.codename。這樣就能控制用戶訪問,如果用戶非法訪問則會(huì)清空session退出登錄。
@permission_required('webcenter.access_role_manage') @login_required def role_index(request): """ 角色管理首頁(yè) :param request: :return: """
同時(shí)在前端模板頁(yè)面中也需要進(jìn)行權(quán)限控制,前端要獲取request對(duì)象的話,后端返回就需要使用render函數(shù),render(request,xxx,xxx),具體代碼就如下:
{% if request.user.is_superuser or 'webcenter.access_user_manage' in request.user.get_group_permissions or 'webcenter.access_role_manage' in request.user.get_group_permissions or 'webcenter.access_log' in request.user.get_group_permissions %} <li class="treeview"> <a href="#" rel="external nofollow" rel="external nofollow" > <i class="fa fa-fw fa-skyatlas"></i> <span>站點(diǎn)管理</span> <i class="fa fa-angle-left pull-right"></i> </a> <ul class="treeview-menu"> {% if request.user.is_superuser or 'webcenter.access_log' in request.user.get_group_permissions %} <li><a href="#" rel="external nofollow" rel="external nofollow" id="log_view">日志管理</a></li> {% endif %} {% if request.user.is_superuser or 'webcenter.access_role_manage' in request.user.get_group_permissions %} <li><a href="/role/index/" rel="external nofollow" >角色管理</a></li> {% endif %} {% if request.user.is_superuser or 'webcenter.access_user_manage' in request.user.get_group_permissions %} <li><a href="/user/index/" rel="external nofollow" >用戶管理</a></li> {% endif %} </ul> </li> {% endif %}
以上這篇django認(rèn)證系統(tǒng)實(shí)現(xiàn)自定義權(quán)限管理的方法就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
基于python3 pyQt5 QtDesignner實(shí)現(xiàn)窗口化猜數(shù)字游戲功能
這篇文章主要介紹了基于python3 pyQt5 QtDesignner實(shí)現(xiàn)窗口化猜數(shù)字游戲功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-07-07Pandas聚合運(yùn)算和分組運(yùn)算的實(shí)現(xiàn)示例
這篇文章主要介紹了Pandas聚合運(yùn)算和分組運(yùn)算的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10Python無法安裝包的一種解決(Requirement already satisfied問題)
這篇文章主要介紹了Python無法安裝包的一種解決(Requirement already satisfied問題),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08用Python進(jìn)行基礎(chǔ)的函數(shù)式編程的教程
這篇文章主要介紹了用Python進(jìn)行基礎(chǔ)的函數(shù)式編程的教程,除了面向?qū)ο缶幊桃馔?、Python還可以進(jìn)行簡(jiǎn)單的不依賴外部變量的函數(shù)式編程,本文介紹了其中的一些基礎(chǔ),需要的朋友可以參考下2015-03-03Python中pandas模塊DataFrame創(chuàng)建方法示例
這篇文章主要介紹了Python中pandas模塊DataFrame創(chuàng)建方法,結(jié)合實(shí)例形式分析了DataFrame的功能,以及pandas模塊基于列表、字段與數(shù)組創(chuàng)建DataFrame的相關(guān)操作技巧,需要的朋友可以參考下2018-06-06