python - ServiceNow JSON Web服务的Python身份验证

标签 python authentication servicenow

我在用python编写一个报告工具,它可以从servicennow的json web服务中获取数据。我们的servicenow实例使用普通用户id/pw身份验证和sha-1认证。我的问题是,我无法使用脚本访问JSON Web服务结果页(https://servicenowserver.com/table.do?JSONv2&sysparm_query=active=true^number=12345678)从中获取数据我可以使用我的脚本登录到主页(https://servicenowserver.com),它进行身份验证并提供http 200,但是当我调用json webservice页面时,它会提供http 401(未经授权)。
一旦我通过浏览器登录到ServiceNow并启动会话,我就可以在一个新的选项卡上调用JSON服务,它会显示结果,但这不适用于我的Python脚本我试图同时使用urllib3requests库和会话参数来保持会话打开,但它们都不起作用。我想我的脚本只是在我调用主页之后立即关闭会话。我也试着不走运地传饼干。
长话短说:它可以在我的浏览器中工作,但如果我使用Python脚本则不行。
您知道如何进行身份验证才能获得json结果吗?或者至少如果有人能指导我如何得到更详细的调试?
以下是我尝试过的解决方案之一:

import requests

s = requests.session()
s.auth = ('user', 'password')
s.verify = 'sn.cer'

r = s.get('https://servicenowserver.com', verify=True)
print (r) # This gives HTTP 200

r2 = s.get ('https://servicenowserver.com/table.do?JSONv2&sysparm_query=active=true^number=12345678', verify=True, cookies=s.cookies)
print (r2) # This gives HTTP 401

最佳答案

我能想出解决办法,所以我在这里发表我将在这里发布的不是我的问题的确切解决方案,而是一种了解和检查如何跟踪身份验证的一般方法。在我的案例中,我使用这种技术来跟踪登录过程。
在我的例子中,services现在使用基于cookie的身份验证,并在4个页面之间来回传递信息第一页生成一个名为NSC的ID,并将其作为cookie传递给第二页,以生成另一个名为SMSESSION ID的ID然后将其与cookie中的nsc id一起传递到第三个页面,以生成最终的jsession id。最后,流程将先前生成的所有3个id传递到cookie中的登录页面,以验证会话。
我用谷歌开发工具来解决这个问题。我建议你做以下事情。
1.)进入google chrome中你想通过的登录页面,等待网站加载。暂时不要登录。
2.)打开开发人员工具(右键单击,检查元素菜单选项)。如果您熟悉其他浏览器的开发功能,也可以。
3.)转到“开发工具”的“应用程序”选项卡,单击左侧菜单栏上的“清除存储”。这将清除为此页存储的所有数据。你也可以在chrome的设置菜单中清除cookies和其他数据。这需要清除页面上已经发生的所有历史步骤,以免造成任何混乱。
4.)完成后,转到dev tools的network选项卡,单击clear菜单选项(在record按钮旁边)。这将清除网络日志历史记录。
5.)下一步,勾选“网络”选项卡上的“保留日志”复选框。这将允许我们跟踪每个步骤,即使在任何重定向的情况下。如果不勾选此选项,则登录页面将您重定向到其他位置后,您将丢失所有数据,因为它将清除网络日志。
(6)现在,当我们删除所有历史数据并设置好一切之后,我们就可以开始调查了使用您的用户id和密码登录到页面,并保持开发人员工具打开,这样您就可以看到所有网络请求等待登录过程完成,然后开始逐个检查网络日志条目。
7.)您将看到一些GET和POST请求这是您的登录流程。双击打开第一个。它将显示按部分组织的信息,就像(常规、响应头、请求头、查询参数、表单数据等)。这是web服务器和客户机(您的机器)之间发生的信息交换你需要用你的脚本模拟相同的内容,这意味着无论你在请求头部分看到什么,你都需要用你的脚本传递完全相同的内容。这样,您将收到完全相同的响应头,并且可以从中获取前进所需的所有信息。
让我给你示范一下。
在我的第一个post请求中,我可以在网络日志中看到以下内容:

General
Request URL:https://mysnserver.net/siteminderagent/forms/dssologinprod.fcc?TYPE=33554433&REALMOID=06-0cffd45f-7ca7-106f-bbab-84fb3af10000&GUID=&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=-SM-28THtkr3KQi%2fJmb193GjY0nVjpKo6ULc%2fJNV5hRyjzC17qWZfgyVPkR%2f7EAWoDVu3Gd3y3kTm3N2p0B8KVp0Hixjin0ZsDZ3&TARGET=-SM-%2f
Request Method:POST
Status Code:302 Found
Remote Address:1.1.1.196:443

Response Headers
Cache-Control:no-store
Connection:Keep-Alive
Content-Length:1541
Content-Type:text/html; charset=iso-8859-1
Date:Wed, 21 Sep 2016 19:11:46 GMT
Keep-Alive:timeout=5, max=496
Location:https://anothersite.com/SmMakeCookie.ccc?SMSESSION=-SM-w0Gp2DpiPEG&PERSIST=0&TARGET=-SM-https%3a%2f%2fservicemanagement%2net%2f
Set-Cookie:SMSESSION=w0Gp2DpiPEGPrLepzXds9qUTVER/Xl75WO36n37IxRpLaE6dwQPwN2+iaNn4rQZODb+65k2Gy9fggnKU04I7rSU6; path=/; domain=.mysnserver.net; secure
Set-Cookie:SMIDENTITY=EoIkGNtD3Y+FBWumdJuml3J78o61Qtc07b73XmqEeze; path=/; domain=.mysnserver.net; secure
Set-Cookie:NSC_1.1.1.196-443-C72169=ffffffffaaa3746145525d5f4f58455e445a4a4253a5;expires=Wed, 21-Sep-2016 21:11:47 GMT;path=/;secure;httponly
Set-Cookie:SMTRYNO=; expires=Fri, 25 Mar 2016 19:11:46 GMT; path=/; domain=.mysnserver.net; secure

Request Headers
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:238
Content-Type:application/x-www-form-urlencoded
Host:mysnserver.net
Origin:https://mysnserver.net
Referer:https://anothersite.net/forms/dssologinprod.fcc?TYPE=33554433&REALMOID=06-0cffd45f-7ca7-106f-bbab-84fb3af10000&GUID=&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=-SM-28THtkr3KQi%2fJmb193GjY0nVjpKo6ULc%2fJNV5hRyjzC17qWZfgyVPkR%2f7EAWoDVu3Gd3y3kTm3N2p0B8KVp0Hixjin0ZsDZ3&TARGET=-SM-%2f
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36

Query String Parameters
TYPE:33554433
REALMOID:06-0cffd45f-7ca7-106f-bbab-84fb3af10000
GUID:
SMAUTHREASON:0
METHOD:GET
SMAGENTNAME:-SM-28THtkr3KQi/Jmb193GjY0nVjpKo6ULc/JNV5hRyjzC17qWZfgyVPkR/7EAWoDVu3Gd3y3kTm3N2p0B8KVp0Hixjin0ZsDZ3
TARGET:-SM-/

Form Data
SMENC:ISO-8859-1
SMLOCALE:US-EN
target:/
smquerydata:
smauthreason:0
smagentname:28THtkr3KQi/Jmb193GjY0nVjpKo6ULc/JNV5hRyjzC17qWZfgyVPkR/7EAWoDVu3Gd3y3kTm3N2p0B8KVp0Hixjin0ZsDZ3
postpreservationdata:
USER:my_userid
PASSWORD:my_password

无论您在请求头部分看到什么,都需要将其传递到第一个URL以获取响应头信息如果您在响应头中看到,我收到了服务器提供的几个id。这意味着我需要在python中准备第一个请求,以传递与请求头中相同的信息。这样地:
auth_url1 = 'https://mysnserver.net/siteminderagent/forms/dssologinprod.fcc?TYPE=33554433&REALMOID=06-0cffd45f-7ca7-106f-bbab-84fb3af10000&GUID=&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=-SM-28THtkr3KQi%2fJmb193GjY0nVjpKo6ULc%2fJNV5hRyjzC17qWZfgyVPkR%2f7EAWoDVu3Gd3y3kTm3N2p0B8KVp0Hixjin0ZsDZ3&TARGET=-SM-%2f'

# Initiating session
s = requests.session()

request_header_1 = {
    'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'Accept-Encoding':'gzip, deflate, br',
    'Accept-Language':'en-US,en;q=0.8',
    'Cache-Control':'max-age=0',
    'Connection':'keep-alive',
    'Content-Length':'238',
    'Content-Type':'application/x-www-form-urlencoded',
    'Host':'mysnserver.net',
    'Origin':'https://mysnserver.net',
    'Referer':'https:///anothersite.net/forms/dssologinprod.fcc?TYPE=33554433&REALMOID=06-0cffd45f-7ca7-106f-bbab-84fb3af10000&GUID=&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=-SM-28THtkr3KQi%2fJmb193GjY0nVjpKo6ULc%2fJNV5hRyjzC17qWZfgyVPkR%2f7EAWoDVu3Gd3y3kTm3N2p0B8KVp0Hixjin0ZsDZ3&TARGET=-SM-%2f',
    'Upgrade-Insecure-Requests':'1',
    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36'
}

form_data_1 = {
    'SMENC':'ISO-8859-1',
    'SMLOCALE':'US-EN',
    'target':'/',
    'smquerydata':'',
    'smauthreason':'0',
    'smagentname':'28THtkr3KQi/Jmb193GjY0nVjpKo6ULc/JNV5hRyjzC17qWZfgyVPkR/7EAWoDVu3Gd3y3kTm3N2p0B8KVp0Hixjin0ZsDZ3',
    'postpreservationdata':'',
    'USER':'my_userid', #<----- Put your user ID here
    'PASSWORD':'my_password' #<----- Put your password here
}
r = s.post(auth_url1, headers=request_header_1, data=form_data_1, verify=False, allow_redirects=False)

# Get NSC ID from the response header which needs to be passed over in the 3rd request
nsc_id = r.cookies.keys()[2] + "=" + r.cookies.values()[2]

就这样如果有更多重定向,则需要遵循相同的过程,直到通过最后一页并验证会话。在此之后,您可以使用收集的cookie信息来验证所有即将提出的请求。如您所见,我使用s = requests.session()命令启动了一个会话,可以使用它提交所有请求,而不必传递所有请求的用户id和pw。当您需要发送get和post请求时,请小心。您可以在标题的“常规信息”部分看到这一点。
还有一个重要的提示如果站点上有重定向,请在allow_redirects=False中使用requests通过这种方式,您可以确保您的请求没有被重定向到其他站点,并且您可以获得正确的响应头信息。

关于python - ServiceNow JSON Web服务的Python身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39603523/

相关文章:

python multiprocessing - 初始化/传递要跨进程使用的数据库连接的最佳方法

authentication - LDAP 身份验证 apache 2.2 错误 500

c - 用户使用 wtmp 在线花费的时间

html - 是否可以设置 iFrame 的样式

python - 如何使用 suds 通过 getRecords 搜索 servicenow 中的日期时间范围?

mysql - 使用专有的 ODBC 驱动程序将 MySQL 连接到外部数据源

python - MultiGraph 中的聚合边属性

python - mrjob:是否可以在 VPC 中运行作业流程?

python - 如何引发 python 异常并包含 Sentry 的附加数据?

java - Dropwizard 身份验证用户