如何在 Django 视图中解码 SAMLResponse?

How to decode SAMLResponse in Django View?

我正在编写一个视图以在已登录到另一个站点的项目中创建一个用户。每当用户登录该站点时,he/she 都会被重定向到 url:https://localhost:127.0.0.1:8000/auth/ad/reply/。 该网站向我发送了一个 SAMLResponse,我想从中提取用户的电子邮件地址、名字和姓氏。

以下是我的 views.py 和 urls.py:

views.py

from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

# Create your views here.
@csrf_exempt
def ad_auth(request):
    response = request.POST.get('SAMLResponse')
    return HttpResponse(response)

urls.py

from django.urls import path

from .views import *

urlpatterns = [
    path('auth/ad/reply/', ad_auth, name='ad_auth'),
]

输出:

PHNhbWxwOlJlc3BvbnNlIElEPSJfOTJmYjAyYTMtN2ZiMC00NjZlLTk0NGItNTQxMjhlOGI5NGM2IiBWZXJzaW9uPSIyLjAiIElzc3VlSW5zdGFudD0iMjAyMC0xMS0xMVQxNDowMDoxMi43NzlaIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9sb2NhbGhvc3Q6ODAwMC9hdXRoL2FkL3JlcGx5LyIgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCI+PElzc3VlciB4bWxucz0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiI+aHR0cHM6Ly9zdHMud2luZG93cy5uZXQvYmYzODg4M2EtOGRlNi00NGFhLWJkYzktODFjMzAzY2YxMDMzLzwvSXNzdWVyPjxzYW1scDpTdGF0dXM+PHNhbWxwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPjwvc2FtbHA6U3RhdHVzPjxBc3NlcnRpb24gSUQ9Il8wYjExNzMwNi03YTI2LTQ2OGQtYTI5Yy1mYTZkMjk2MTQ3MDAiIElzc3VlSW5zdGFudD0iMjAyMC0xMS0xMVQxNDowMDoxMi43NjlaIiBWZXJzaW9uPSIyLjAiIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj48SXNzdWVyPmh0dHBzOi8vc3RzLndpbmRvd3MubmV0L2JmMzg4ODNhLThkZTYtNDRhYS1iZGM5LTgxYzMwM2NmMTAzMy88L0lzc3Vlcj48U2lnbmF0dXJlIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48U2lnbmVkSW5mbz48Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjxTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNyc2Etc2hhMjU2Ii8+PFJlZmVyZW5jZSBVUkk9IiNfMGIxMTczMDYtN2EyNi00NjhkLWEyOWMtZmE2ZDI5NjE0NzAwIj48VHJhbnNmb3Jtcz48VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PC9UcmFuc2Zvcm1zPjxEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNzaGEyNTYiLz48RGlnZXN0VmFsdWU+YjdXZGtxd0d0VncyVGIxbG1ybklabHI3bXNDektFemkreGZrMVZTT2tMQT08L0RpZ2VzdFZhbHVlPjwvUmVmZXJlbmNlPjwvU2lnbmVkSW5mbz48U2lnbmF0dXJlVmFsdWU+aW9ldm5INHIyb05ra1QvaXhrelVSQ01sKzQ4enNVQUdFTFBmWmZDMXVsTmROWE5EcVVKelVFL2FYTzR6MzduWCtDY1htcGw4ZmZrRlNtNHFWNS9WaTV1TzkreFB5U3QvejhlWXV3WGg5THkvVGFsbmlCVTZ5L2JCMFF1NW9pb2pXczYxVWlIQlhGMTlGVy9WTXd2WVdlUnpXNGdKUU03cDNNdVE0MjV6Zk9PaHk2V2puNW1MU1RkOVNZT2pSOHkraWlOKzZDdHJNd2NVTk9LNXFMTFNSOGdpdUNkSVZyTUY2V2lIUkZWTjY1SlRsYXNKSVpuSWw0dldnUDdkaUJvdDB1cmtkR28wb1djMU4vQ3FOOWN1OENlTTJtTmc5SW5XS1RHWGJVaDhuZDNtcEwwa1RnZE9OOUpxMUhWTytsck94ZVcwZ0dacDB4VmVEMERnRlBHU0pBPT08L1NpZ25hdHVyZVZhbHVlPjxLZXlJbmZvPjxYNTA5RGF0YT48WDUwOUNlcnRpZmljYXRlPk1JSUM4RENDQWRpZ0F3SUJBZ0lRSk1TOWVpdVJQSVZCeVY5NW5TeDBhakFOQmdrcWhraUc5dzBCQVFzRkFEQTBNVEl3TUFZRFZRUURFeWxOYVdOeWIzTnZablFnUVhwMWNtVWdSbVZrWlhKaGRHVmtJRk5UVHlCRFpYSjBhV1pwWTJGMFpUQWVGdzB5TURFd01EWXdOVEkxTkRWYUZ3MHlNekV3TURZd05USTFORFZhTURReE1qQXdCZ05WQkFNVEtVMXBZM0p2YzI5bWRDQkJlblZ5WlNCR1pXUmxjbUYwWldRZ1UxTlBJRU5sY25ScFptbGpZWFJsTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF0WmZVZjQzNE1HeVI1ZzdPUzViMFhzV2tEUVYrYk9BWkpuZlROZTE2R1ZQV2U1ZnBhdW9XaDY1NUZjQVF3OXdEd3Z3eUJsa04vc1pqc1JnMTFLRmZyeGZkNmhkQk1Ka3FpKzN3MENMYTZzWDg5VzBmZzhnWXA3bDN4WVFBVG94RDI2MWhuT1dRaXE5em5nS2V4dVNWaW8wL25IdXNBeEdvZDdMV1A5ckRqWGh6bDRBWXQrcjZpVWt3QlNFQnoyeE41RU4rRnVPQjY5UlpaVFNGRzdUVVBCd1NseWlJZms4L3JpclhHOVFhMVk2SmFySVY4M1JSTjJKM1lpdU91Q3E2WWxseDFyNXlJVmlONlFSOG1zTlN0cmFaSS9hTGI5QjFaajJVaFBwNG8veXkwemFIQnV3Y0xjc1k4RDNSWFExblJLMVFSS041Y28rUUhkeEVrdmdicFFJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUJxVHhkRTZxTHd2M0tmelNhZDU5NkJuNU9aNWVxakp5MW1vVGZoY0dHOVpBYnh5eDlDL1N6MFkyaW02dCs4YmQwdzdqUG51NHA1YWZjMGUyQ2tIL0IyZElldHBkcWpvdEdlSmZhUng3OVJJSTF6OU9LQUZQcDlkYzY5eGhndDNYN3RuZlJhVDNmeml3QSt3Z3VocjJ0YUpRUHVLOVkyL2w0VTI1N0JUNFkvMzd5S0EwM0lDakZTcXZTTzE4bmx5UkUzRVArbTEyR0tPTVYvVjZwTjJqTFRJV2I5cXIyc1E2VGl1alc3T2g0S0lyTk5pRWx2QnFRcWZyNE5OTEZuZCt1RHBWUFhHc0JYQ2NkOXZhQWswelJFUGxwMUdKQW0yOHZJMnNPLytWcjZ3cmVoR0gwVFNmOU5DQkY2cDUzVHN0RWNOVldCYUNHTkFwQlZrY0RKaGRYTDwvWDUwOUNlcnRpZmljYXRlPjwvWDUwOURhdGE+PC9LZXlJbmZvPjwvU2lnbmF0dXJlPjxTdWJqZWN0PjxOYW1lSUQgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjE6bmFtZWlkLWZvcm1hdDplbWFpbEFkZHJlc3MiPmxpbmdheWF0YWpheTI4MTBfZ21haWwuY29tI0VYVCNAa3Jpc3AxNTA2Z21haWwub25taWNyb3NvZnQuY29tPC9OYW1lSUQ+PFN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgTm90T25PckFmdGVyPSIyMDIwLTExLTExVDE1OjAwOjEyLjM4OFoiIFJlY2lwaWVudD0iaHR0cHM6Ly9sb2NhbGhvc3Q6ODAwMC9hdXRoL2FkL3JlcGx5LyIvPjwvU3ViamVjdENvbmZpcm1hdGlvbj48L1N1YmplY3Q+PENvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDIwLTExLTExVDEzOjU1OjEyLjM4OFoiIE5vdE9uT3JBZnRlcj0iMjAyMC0xMS0xMVQxNTowMDoxMi4zODhaIj48QXVkaWVuY2VSZXN0cmljdGlvbj48QXVkaWVuY2U+RGVsbGNhbGNJRDwvQXVkaWVuY2U+PC9BdWRpZW5jZVJlc3RyaWN0aW9uPjwvQ29uZGl0aW9ucz48QXR0cmlidXRlU3RhdGVtZW50PjxBdHRyaWJ1dGUgTmFtZT0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9pZGVudGl0eS9jbGFpbXMvdGVuYW50aWQiPjxBdHRyaWJ1dGVWYWx1ZT5iZjM4ODgzYS04ZGU2LTQ0YWEtYmRjOS04MWMzMDNjZjEwMzM8L0F0dHJpYnV0ZVZhbHVlPjwvQXR0cmlidXRlPjxBdHRyaWJ1dGUgTmFtZT0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9pZGVudGl0eS9jbGFpbXMvb2JqZWN0aWRlbnRpZmllciI+PEF0dHJpYnV0ZVZhbHVlPjg0MjYwMmMxLWNhZDQtNDg2OC05Yzk5LWZjMDhmOTExNzk1MzwvQXR0cmlidXRlVmFsdWU+PC9BdHRyaWJ1dGU+PEF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL2lkZW50aXR5L2NsYWltcy9kaXNwbGF5bmFtZSI+PEF0dHJpYnV0ZVZhbHVlPkFqYXkgTGluZ2F5YXQ8L0F0dHJpYnV0ZVZhbHVlPjwvQXR0cmlidXRlPjxBdHRyaWJ1dGUgTmFtZT0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9pZGVudGl0eS9jbGFpbXMvaWRlbnRpdHlwcm92aWRlciI+PEF0dHJpYnV0ZVZhbHVlPmxpdmUuY29tPC9BdHRyaWJ1dGVWYWx1ZT48L0F0dHJpYnV0ZT48QXR0cmlidXRlIE5hbWU9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vY2xhaW1zL2F1dGhubWV0aG9kc3JlZmVyZW5jZXMiPjxBdHRyaWJ1dGVWYWx1ZT5odHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvYXV0aGVudGljYXRpb25tZXRob2QvcGFzc3dvcmQ8L0F0dHJpYnV0ZVZhbHVlPjwvQXR0cmlidXRlPjxBdHRyaWJ1dGUgTmFtZT0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvZ2l2ZW5uYW1lIj48QXR0cmlidXRlVmFsdWU+QWpheTwvQXR0cmlidXRlVmFsdWU+PC9BdHRyaWJ1dGU+PEF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9zdXJuYW1lIj48QXR0cmlidXRlVmFsdWU+TGluZ2F5YXQ8L0F0dHJpYnV0ZVZhbHVlPjwvQXR0cmlidXRlPjxBdHRyaWJ1dGUgTmFtZT0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvZW1haWxhZGRyZXNzIj48QXR0cmlidXRlVmFsdWU+bGluZ2F5YXRhamF5MjgxMEBnbWFpbC5jb208L0F0dHJpYnV0ZVZhbHVlPjwvQXR0cmlidXRlPjxBdHRyaWJ1dGUgTmFtZT0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvbmFtZSI+PEF0dHJpYnV0ZVZhbHVlPmxpbmdheWF0YWpheTI4MTBfZ21haWwuY29tI0VYVCNAa3Jpc3AxNTA2Z21haWwub25taWNyb3NvZnQuY29tPC9BdHRyaWJ1dGVWYWx1ZT48L0F0dHJpYnV0ZT48L0F0dHJpYnV0ZVN0YXRlbWVudD48QXV0aG5TdGF0ZW1lbnQgQXV0aG5JbnN0YW50PSIyMDIwLTExLTExVDA3OjI4OjM1LjAwMFoiIFNlc3Npb25JbmRleD0iXzBiMTE3MzA2LTdhMjYtNDY4ZC1hMjljLWZhNmQyOTYxNDcwMCI+PEF1dGhuQ29udGV4dD48QXV0aG5Db250ZXh0Q2xhc3NSZWY+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFjOmNsYXNzZXM6UGFzc3dvcmQ8L0F1dGhuQ29udGV4dENsYXNzUmVmPjwvQXV0aG5Db250ZXh0PjwvQXV0aG5TdGF0ZW1lbnQ+PC9Bc3NlcnRpb24+PC9zYW1scDpSZXNwb25zZT4=

如何从以下 SAMLResponse 中提取信息? 提前致谢。

那是向您发送一个 base64 编码的字符串。 解码它,你会发现它是xml.

电子邮件属性看起来像这样

<AttributeValue>xxxxxxxxx2810@gmail.com</AttributeValue>

一些 sudo 代码让你开始

import base64

foo = base64.b64decode("PHNhbWxwOlJlc3BvbnN....") # put your entire string here

print(foo)

您还可以使用 pysaml2 和 djangosaml 模块来解密 SAMLResponse。