2011-05-11 45 views
2

我對Python世界頗爲陌生。因爲我在設計以及決定階段是否選擇python作爲實現該軟件的主要語言。其任務是: - 實現一組平穩的Web服務 - 將http方法授權給特定的用戶組,因爲它需要使用xacml作爲策略定義(或者可以是其他標準),並且對於信息saml 。交換授權Python中的REST服務

預先感謝您的建議, 埃裏克

+1

你的問題是什麼? – 2011-05-11 12:38:08

+0

你應該發佈你的代碼和你的問題。你作業的描述並不是很感興趣。 – 2011-05-11 13:44:25

+0

@Eli Bendersky問題是關於寧靜服務的訪問保護, http方法。因此,決定允許哪個用戶執行一個安靜的服務上的目標資源的http方法? – user748650 2011-05-12 10:07:20

回答

1

如果你的問題是,你可以用它來實現這些RESTful服務什麼庫,然後看看到BaseHTTPServer模塊標準Python庫。

下面的代碼顯示它是多麼容易實現一個簡單的服務器接受GET請求:

class MyHandler(BaseHTTPRequestHandler): 

    def do_GET(self): 
     try: 
      f = open(curdir + sep + self.path) #self.path has /test.html 
      self.send_response(200) 
      self.send_header('Content-type', 'text/html') 
      self.end_headers() 
      self.wfile.write(f.read()) 
      f.close() 
     except IOError: 
      self.send_error(404,'File Not Found: %s' % self.path) 

def main(): 
    try: 
     server = HTTPServer(('', 80), MyHandler) 
     print 'Welcome to the machine...' 
     server.serve_forever() 
    except KeyboardInterrupt: 
     print '^C received, shutting down server' 
     server.socket.close() 

if __name__ == '__main__': 
    main() 

當然,代碼是不是從我自己,我發現它here

+0

謝謝,這部分回答了我的問題。具體而言,不是如何開發一種寧靜的服務,而是更多地從其他服務授權主題。用例是訪問保護http方法,這意味着哪些用戶組可以執行哪種方法以及哪些資源? – user748650 2011-05-12 10:02:58

0

使用Python,您希望創建一個XACML請求,其中包含用戶的ID(您可以從通常在進行身份驗證之前進行的身份驗證階段獲得該請求),並添加有關用戶所定位的WS的信息。這可能是URI,HTTP方法太...

最後,你可能會喜歡STHG:

<?xml version="1.0" encoding="UTF-8"?><xacml-ctx:Request xmlns:xacml-ctx="urn:oasis:names:tc:xacml:2.0:context:schema:os"> 
    <xacml-ctx:Subject SubjectCategory="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"> 
     <xacml-ctx:Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" DataType="http://www.w3.org/2001/XMLSchema#string"> 
     <xacml-ctx:AttributeValue>Alice</xacml-ctx:AttributeValue> 
     </xacml-ctx:Attribute> 
    </xacml-ctx:Subject> 
    <xacml-ctx:Resource> 
     <xacml-ctx:Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" DataType="http://www.w3.org/2001/XMLSchema#string"> 
     <xacml-ctx:AttributeValue>/someuri/myapi/target.py</xacml-ctx:AttributeValue> 
     </xacml-ctx:Attribute> 
    </xacml-ctx:Resource> 
    <xacml-ctx:Action> 
     <xacml-ctx:Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" DataType="http://www.w3.org/2001/XMLSchema#string"> 
     <xacml-ctx:AttributeValue>GET</xacml-ctx:AttributeValue> 
     </xacml-ctx:Attribute> 
    </xacml-ctx:Action> 
    <xacml-ctx:Environment> 
    </xacml-ctx:Environment> 
</xacml-ctx:Request> 

需要構建使用Python LXML例如請求和。

響應看起來像

<xacml-ctx:Response xmlns:xacml-ctx="urn:oasis:names:tc:xacml:2.0:context:schema:os"> 
    <xacml-ctx:Result> 
    <xacml-ctx:Decision>Permit</xacml-ctx:Decision> 
    <xacml-ctx:Status> 
     <xacml-ctx:StatusCode Value="urn:oasis:names:tc:xacml:1.0:status:ok"/> 
    </xacml-ctx:Status> 
    </xacml-ctx:Result> 
</xacml-ctx:Response> 

如此反覆,你需要解析的XML例如提取的決定許可證。我爲XACML PDP寫了一個基本的類似REST的接口,您只需將HTTP GET發送給通過變量作爲GET變量的URI即可。 http://www.xacml.eu/AuthZ/?a=alice&b=/someuri/myapi/target.py&c=GET

這有幫助嗎?

0

我同意Constantinius BaseHTTPServer是一種在Python中執行RESTful的好方法。它預裝了Python 2.7,並且比gunicorn/flask/wsgi/gevent在這方面的功能要好得多。並支持您可能想要的流式傳輸。

下面是一個示例,顯示Web瀏覽器如何對BaseHTTPServer執行遠程POST調用並獲取數據。 (放在靜態/你好。HTML通過Python的服務):(測試)

<html><head><meta charset="utf-8"/></head><body> 
Hello. 

<script> 

var xhr = new XMLHttpRequest(); 
xhr.open("POST", "/postman", true); 
xhr.setRequestHeader('Content-Type', 'application/json'); 
xhr.send(JSON.stringify({ 
    value: 'value' 
})); 
xhr.onload = function() { 
    console.log("HELLO") 
    console.log(this.responseText); 
    var data = JSON.parse(this.responseText); 
    console.log(data); 
} 

</script></body></html> 

Python的服務器:

import time, threading, socket, SocketServer, BaseHTTPServer 
import os, traceback, sys, json 


log_lock   = threading.Lock() 
log_next_thread_id = 0 

# Local log functiondef 


def Log(module, msg): 
    with log_lock: 
     thread = threading.current_thread().__name__ 
     msg = "%s %s: %s" % (module, thread, msg) 
     sys.stderr.write(msg + '\n') 

def Log_Traceback(): 
    t = traceback.format_exc().strip('\n').split('\n') 
    if ', in ' in t[-3]: 
     t[-3] = t[-3].replace(', in','\n***\n*** In') + '(...):' 
     t[-2] += '\n***' 
    err = '\n*** '.join(t[-3:]).replace('"','').replace(' File ', '') 
    err = err.replace(', line',':') 
    Log("Traceback", '\n'.join(t[:-3]) + '\n\n\n***\n*** ' + err + '\n***\n\n') 

    os._exit(4) 

def Set_Thread_Label(s): 
    global log_next_thread_id 
    with log_lock: 
     threading.current_thread().__name__ = "%d%s" \ 
      % (log_next_thread_id, s) 
     log_next_thread_id += 1 


class Handler(BaseHTTPServer.BaseHTTPRequestHandler): 

    def do_GET(self): 
     Set_Thread_Label(self.path + "[get]") 
     try: 
      Log("HTTP", "PATH='%s'" % self.path) 
      with open('static' + self.path) as f: 
       data = f.read() 
      Log("Static", "DATA='%s'" % data) 
      self.send_response(200) 
      self.send_header("Content-type", "text/html") 
      self.end_headers() 
      self.wfile.write(data) 
     except: 
      Log_Traceback() 

    def do_POST(self): 
     Set_Thread_Label(self.path + "[post]") 
     try: 
      length = int(self.headers.getheader('content-length')) 
      req = self.rfile.read(length) 
      Log("HTTP", "PATH='%s'" % self.path) 
      Log("URL", "request data = %s" % req) 
      req = json.loads(req) 
      response = {'req': req} 
      response = json.dumps(response) 
      Log("URL", "response data = %s" % response) 
      self.send_response(200) 
      self.send_header("Content-type", "application/json") 
      self.send_header("content-length", str(len(response))) 
      self.end_headers() 
      self.wfile.write(response) 
     except: 
      Log_Traceback() 


# Create ONE socket. 
addr = ('', 8000) 
sock = socket.socket (socket.AF_INET, socket.SOCK_STREAM) 
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
sock.bind(addr) 
sock.listen(5) 

# Launch 10 listener threads. 
class Thread(threading.Thread): 
    def __init__(self, i): 
     threading.Thread.__init__(self) 
     self.i = i 
     self.daemon = True 
     self.start() 
    def run(self): 
     httpd = BaseHTTPServer.HTTPServer(addr, Handler, False) 

     # Prevent the HTTP server from re-binding every handler. 
     # https://stackoverflow.com/questions/46210672/ 
     httpd.socket = sock 
     httpd.server_bind = self.server_close = lambda self: None 

     httpd.serve_forever() 
[Thread(i) for i in range(10)] 
time.sleep(9e9) 

控制檯日誌(鉻):

HELLO 
hello.html:14 {"req": {"value": "value"}} 
hello.html:16 
{req: {…}} 
req 
: 
{value: "value"} 
__proto__ 
: 
Object 

控制檯日誌(火狐):

GET 
http://XXXXX:8000/hello.html [HTTP/1.0 200 OK 0ms] 
POST 
XHR 
http://XXXXX:8000/postman [HTTP/1.0 200 OK 0ms] 
HELLO hello.html:13:3 
{"req": {"value": "value"}} hello.html:14:3 
Object { req: Object } 

控制檯日誌(Edge):

HTML1300: Navigation occurred. 
hello.html 
HTML1527: DOCTYPE expected. Consider adding a valid HTML5 doctype: "<!DOCTYPE html>". 
hello.html (1,1) 
Current window: XXXXX/hello.html 
HELLO 
hello.html (13,3) 
{"req": {"value": "value"}} 
hello.html (14,3) 
[object Object] 
hello.html (16,3) 
    { 
     [functions]: , 
     __proto__: { }, 
     req: { 
     [functions]: , 
     __proto__: { }, 
     value: "value" 
     } 
    } 

Python的日誌:

HTTP 8/postman[post]: PATH='/postman' 
URL 8/postman[post]: request data = {"value":"value"} 
URL 8/postman[post]: response data = {"req": {"value": "value"}} 

你也可以將它傳遞給BaseHTTPServer之前包裹的插座很容易地添加SSL。