django實現SSO


 

前言

公司的各種運維平台越來越多,用戶再每個平台都注冊賬號,密碼,密碼太多記不住不說,然后有的平台過一段時間還得修改密碼,煩!
還不如弄個統一登錄平台!!

 

需求分析

造這輛大車,首先就得造兩個輪子
首先,聯想到實現方式一-----共享session:大致說的就是把cookie 跨域,然后同域的去拿這個cookie找服務端的session,
如果session 是有效,那么就登錄成功,當然,服務端的session 也得共享一下,而且格式還得保持統一。 這樣不好不好,剛有這個想法,就被后面的大傻個安全給否了,說那你的一個站癱瘓了,其他的不就玩完了。 接着實現方式二:大致就是子系統登錄時,把要訪問的地址信息啥的通過加密后的token,作為參數去請求統一登錄,
然后統一登錄解密token發現里面包含的信息啥的是對的,登錄成功后,然后就把用戶的信息和其他的一些玩意返回給子系統,子系統直接login就ok了。 這種方式感覺可搞,后面的大傻個也挑不出毛病。 最后終於找到了這倆輪子: django
-sso-simple django-auth-ldap

 

需求實現

集成ladp登錄

# 新建一個django項目,安裝兩個輪子,創建一個app

# 配置settings 
AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',
    'django_auth_ldap.backend.LDAPBackend',
)
#在認證后端要加上ldap認證,當然加前加都可以,用戶認證的時候是會按照順序認證的,認證成功就返回,如果都失敗了,那么就失敗了。 

import ldap
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType, PosixGroupType, LDAPGroupQuery
# 這些意思就是配置ldap基礎信息,同步那些用戶信息到django的user里去。
AUTH_LDAP_SERVER_URI = "ldap://xxx.com:389"
AUTH_LDAP_USER_DN_TEMPLATE = "uid=%(user)s,ou=People,dc=xxx,dc=com,dc=cn"
AUTH_LDAP_USER_ATTR_MAP = {
    "username": "uid", "first_name": "cn",
}
AUTH_LDAP_ALWAYS_UPDATE_USER = True


# posixGroup
# 下面是同步用戶組到django的用戶組中去。
AUTH_LDAP_GROUP_SEARCH = LDAPSearch('ou=group,dc=xxx,dc=com,dc=cn', ldap.SCOPE_SUBTREE,"(objectClass=posixGroup)")
# 這個type 很重要,各位看客注意自己的ldap 組是什么類型
AUTH_LDAP_GROUP_TYPE = PosixGroupType()


# 同步ldap的用戶組到用戶信息里去,比如dev 或者研發組的 用戶就是激活的.
AUTH_LDAP_FIND_GROUP_PERMS = True
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
    "is_active":
        LDAPGroupQuery("cn=dev,ou=group,dc=xxx,dc=com,dc=cn") |
        LDAPGroupQuery("cn=ops,ou=group,dc=xxx,dc=com,dc=cn")

    "is_staff": "cn=ops,ou=group,dc=xxx,dc=com,dc=cn",
    "is_superuser": "cn=admin,ou=group,dc=xxx,dc=com,dc=cn"
}
AUTH_LDAP_CACHE_GROUPS = True
AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600
AUTH_LDAP_MIRROR_GROUPS = True

# 以上配置完成之后可以接入ldap驗證一下。
# 如果有問題的直接看django-ldap-auth 文檔就好啦。
View Code

sso實現

# django的登錄,還是那個登錄
def sso_login(request):
    """
    登錄成功后要設置用戶信息到session 中去 。
    """
    if request.method == 'GET':
        if request.user.is_authenticated:
            return HttpResponseRedirect(redirect_url)
        return render(request, 'login.html')
    else:
        username = request.POST.get('username')
        password = request.POST.get('password')
        next_url = request.GET.get('next', None)
        user = authenticate(username=username, password=password)
        if user:
            ret = login(request, user)
            if not next_url:
                return HttpResponseRedirect(redirect_url)
            else:
                return HttpResponseRedirect(next_url)
        else:
            error_message = '用戶名或密碼錯誤'
            return render(request, 'login.html', locals())
View Code

url路由部分

# server 比較關鍵
sso_server = SSOServer()
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^success/', success,name="success"),
    url(r'^logout/', sso_logout,name="logout"),
    url(r'^ssologin', sso_login,name="ssologin"),
    url(r'^server/', include(sso_server.get_urls())),
    url(r'^$', sso_login,name="ssologin"),
]
View Code

源碼分析

認證流程

流程文字版

1.客戶端訪問某個需要登錄的地方,到了login_view這里,會把要訪問的地址信息放到 redirect_to中去 
2.然后把redirect_to 當做參數 去服務端request-token,請求一下token,服務端會返回一個token的request_token 。 
3.然后帶着這個token去訪問authorize,登錄成功后 服務端去驗證token並檢測這個用戶是否有效。 
4.然后客戶端帶着access_token 去獲取用戶信息,獲取之后再登錄。

流程圖解

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM