django-simple-sso原始workflow
- User wants to log into a Client by clicking a “Login” button. The initially requested URL can be passed using the next GET parameter.
- The Client’s Python code does a HTTP request to the Server to request a authentication token, this is called the Request Token Request.
- The Server returns a Request Token.
- The Client redirects the User to a view on the Server using the Request Token, this is the Authorization Request.
- If the user is not logged in the the Server, they are prompted to log in.
- The user is redirected to the Client including the Request Token and a Auth Token, this is the Authentication Request.
- The Client’s Python code does a HTTP request to the Server to verify the Auth Token, this is called the Auth Token Verification Request.
- If the Auth Token is valid, the Server returns a serialized Django User object.
- The Client logs the user in using the Django User recieved from the Server.
前后端分離項目使用django-simple-sso的驗證過程
image.png
- 用戶請求前端頁面缝驳,前端頁面請求get_user_info接口,session有效可以返回用戶信息钝鸽。
- 當(dāng)無法獲取用戶信息時薯定,說明client端登陸失效隙轻。調(diào)用client端登陸接口埠帕。此接口會向server端獲取request-token。server端會保存此token到token表中玖绿。
- user被重定向到server端的authorize接口敛瓷,參數(shù)request-token。驗證server端session是否有效斑匪,
"GET /server/authorize/?token=adpvzavQValZBGCzpGJE2QpnRQxNJVlWpQJ4h0uP8d2CuK0P7tBGuBXbUuyBqQyT HTTP/1.1" 302 0
- 無效則重定向到登陸頁面呐籽,登陸后再次請求authorize接口。
- 有效則重定向到client端authenticate接口蚀瘸。此接口會向server端請求用戶信息狡蝶,并且請用戶信息保存在client端的auth_user表中
部分代碼
因為要實現(xiàn)不同域名之間的跳轉(zhuǎn),所以覆蓋了原代碼中的get_next方法贮勃,不進(jìn)行任何安全限制贪惹。
class ClientLoginView(client.LoginView):
def get_next(self):
return self.request.GET.get('next', None) # 允許跳轉(zhuǎn)到外部域
class ClientAuthenticateView(client.AuthenticateView):
def get(self, request):
raw_access_token = request.GET['access_token']
access_token = URLSafeTimedSerializer(self.client.private_key).loads(raw_access_token)
user = self.client.get_user(access_token)
user.backend = self.client.backend
login(request, user)
next = self.get_next()
return HttpResponseRedirect(next)
def get_next(self):
return self.request.GET.get('next', None) # 允許跳轉(zhuǎn)到外部域