经过几天的努力,我认识到我缺乏知识或技能水平,无法将所有这些部分组合起来完成这个项目。因此,我呼吁并感激任何可以帮助我的人。
技术
- CentOS 7.5
- Python 3.6.0
- Django 1.10.5
- PostreSQL 9.2
- Microsoft CRM Dynamics 365在线版,其中包含最新的客户数据,因此必须使用Web API:https://msdn.microsoft.com/en-us/library/gg334767.aspx
问题
- CRM中包含最新的客户数据,并希望将其导入PostgreSQL以供多种用途
- 希望使用
www_fdw
,因为它是我见过的唯一一个可以使用Web API的PostgreSQL外部数据包装器:https://github.com/cyga/www_fdw/wiki - Dynamics Web API使用OAuth2,而
www_fdw
不支持任何类型的身份验证 - 与
www_fdw
的开发人员交谈后,建议创建一个代理服务器来处理与Microsoft的OAuth2身份验证 - 使用
www_fdw
的PostgreSQL将与代理服务器通信,代理服务器将向Microsoft发送身份验证,最终能够将Web API视为外部表格,使其像任何其他表格一样被处理
三个部分及已尝试的内容
三个部分= www_fdw
+ 代理服务器 + OAuth2
www_fdw
: I have setup using the following parameters based on this: https://github.com/cyga/www_fdw/wiki/ExamplesDROP EXTENSION IF EXISTS www_fdw CASCADE; CREATE EXTENSION www_fdw; CREATE SERVER crm FOREIGN DATA WRAPPER www_fdw OPTIONS (uri 'http://localhost:12345'); -- proxy server CREATE USER MAPPING FOR current_user SERVER crm; -- for testing trying to get 'name' out of the CRM 'accounts' table and naming the foreign table the same as the table in CRM CREATE FOREIGN TABLE accounts ( name varchar(255) ) SERVER crm;
crmproxytest.py
for the proxy server, I have been trying to make a bare bones one using this link: http://effbot.org/librarybook/simplehttpserver.htmimport socketserver import http.server import urllib PORT = 12345 class Proxy(http.server.SimpleHTTPRequestHandler): def do_GET(self): self.copyfile(urllib.urlopen(self.path), self.wfile) httpd = socketserver.ForkingTCPServer(('', PORT), Proxy) print ("serving at port", PORT) httpd.serve_forever()
This seems to work as it says
serving at port 12345
on console, shows up runningnmap -sT -O localhost
, there is some activity on the console running the server whennmap
is run. Otherwise can't get any activity out of it.Running
SELECT * FROM accounts
from PostgreSQL results inCan't get a response from server: Failed to connect to ::1: Permission denied
.OAuth2. I put together
crm.py
and got it working after talking to Microsoft, sorting through their documentation, and the finding this link: http://alexanderdevelopment.net/post/2016/11/27/dynamics-365-and-python-integration-using-the-web-api/In a nutshell, you have to register your app with Azure Active Directory so that you can get a
client_id
,client_secret
, in addition to being able to obtain theOAuth 2.0 Token URI
and theOAuth 2.0 Authorization URI
. You can then send a request to theauthorizationendpoint
, which if the credentials match it returns an token, the token is then sent to thetokenendpoint
and access to the Web API is ultimately granted.This is the code I ended up with that works, retrieves data from the Dynamics Web API, and populates it in the console:
import requests import json #set these values to retrieve the oauth token crmorg = 'https://ORG.crm.dynamics.com' #base url for crm org clientid = '00000000-0000-0000-0000-000000000000' #application client id client_secret = 'SUPERSECRET' username = 'asd@asd.com' #username userpassword = 'qwerty' #password authorizationendpoint = 'https://login.windows.net/ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ/oauth2/authorize' tokenendpoint = 'https://login.windows.net/ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ/oauth2/token' #oauth token endpoint #set these values to query your crm data crmwebapi = 'https://ORG.api.crm.dynamics.com/api/data/v8.2' #full path to web api endpoint crmwebapiquery = '/accounts?$select=name&$orderby=name' #web api query (include leading /) #build the authorization token request tokenpost = { 'client_id':clientid, 'client_secret': client_secret, 'resource':crmorg, 'oauthUrl': authorizationendpoint, 'username':username, 'password':userpassword, 'grant_type':'password' } #make the token request tokenres = requests.post(tokenendpoint, data=tokenpost) #check the value of tokenres print(tokenres) #set accesstoken variable to empty string accesstoken = '' #extract the access token try: accesstoken = tokenres.json()['access_token'] except(KeyError): #handle any missing key errors print('Could not get access token') # check point for debugging # print(accesstoken) #if we have an accesstoken if(accesstoken!=''): #prepare the crm request headers crmrequestheaders = { 'Authorization': 'Bearer ' + accesstoken, 'OData-MaxVersion': '4.0', 'OData-Version': '4.0', 'Accept': 'application/json', 'Content-Type': 'application/json; charset=utf-8', 'Prefer': 'odata.maxpagesize=500', 'Prefer': 'odata.include-annotations=OData.Community.Display.V1.FormattedValue' } #make the crm request crmres = requests.get(crmwebapi+crmwebapiquery, headers=crmrequestheaders) try: #get the response json crmresults = crmres.json() #loop through it for x in crmresults['value']: # print (x['fullname'] + ' - ' + x['contactid']) print (x['name']) except KeyError: #handle any missing key errors print('Could not parse CRM results')
This works like a charm, but is really for testing the OAuth2. The query in combination of variables
crmwebapi
andcrmwebapiquery
doesn't really need to be in there since PostgreSQL, if the FDW is working right, should allow for running SQL queries against the Web API.
无论如何,我希望我已经解释得足够清楚了。看起来我已经获得了三个独立的工作或部分工作的谜题,但把它们汇集在一起就是我的难点。crm.py
和crmtest.py
可能需要合并,但不确定如何合并。
提前感谢您的帮助!
编辑:显然到处都是www_ftw
而不是www_fdw
。