Python中的授权REST服务

Python中的授权REST服务,python,web-services,rest,saml,xacml,Python,Web Services,Rest,Saml,Xacml,我在设计阶段,也在决定是否选择python作为实现软件的主要语言。任务是: 实现一组restful web服务 将http方法授权给特定的用户组,为此需要使用xacml作为策略定义(或者可以是另一个标准),使用saml作为信息。交换 如果您的问题是可以使用哪些库来实现这些RESTful服务,那么请查看标准python库的模块 下面的代码显示了实现一个简单的服务器接受GET请求是多么容易: class MyHandler(BaseHTTPRequestHandler): def do_

我在设计阶段,也在决定是否选择python作为实现软件的主要语言。任务是:

  • 实现一组restful web服务
  • 将http方法授权给特定的用户组,为此需要使用xacml作为策略定义(或者可以是另一个标准),使用saml作为信息。交换

如果您的问题是可以使用哪些库来实现这些RESTful服务,那么请查看标准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()

当然,代码不是我自己写的,我找到的。

使用Python,您可能希望创建一个包含用户id的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>

爱丽丝
/someuri/myapi/target.py
得到
例如,您需要使用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以提取决策,例如Permit。我为XACML PDP编写了一个基本的REST类接口,在这个接口中,您所要做的就是向URI发送一个HTTPGET,并将变量作为GET变量传递


这有帮助吗?

我同意Constantinius的观点,即
BaseHTTPServer
是用Python实现RESTful的一种很好的方法。它是用Python2.7预先安装的,在这方面比gunicorn/flask/wsgi/gevent的伸缩性好得多。并支持流式传输,这可能是您今后需要的

下面的示例显示了web浏览器如何对BaseHTTPServer进行远程POST调用并返回数据

JS(放在static/hello.html中,通过Python提供服务):

控制台日志(chrome):

控制台日志(firefox):

控制台日志(边缘):


此外,在将套接字传递给BaseHTTPServer之前,您还可以通过包装套接字来轻松添加SSL。

您可能应该将您的问题与代码一起发布。我们对你的家庭作业不太感兴趣。@Eli Bendersky问题是关于restful服务的访问保护,特别是http方法。因此,决定允许哪个用户在restful服务上执行目标资源的哪个http方法?@user748650:这里没有问题。建议可以包括任何内容。(1) 阅读REST,(2)选择任何Python web框架,(3)使用该框架。(4) 使用
lxml
解析XACML。现在还不清楚你想要的是什么,这些东西已经不常见了。请问一些具体的问题,以避免对你可能已经做过的事情得到无用的建议。你的问题是什么?谢谢,这部分回答了我的问题。具体来说,不是如何开发restful服务,而是更多地授权rest服务中的主题。用例是访问保护http方法,这意味着什么用户组可以在什么资源上执行哪个方法?
<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>
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 }
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"
      }
   }
HTTP 8/postman[post]: PATH='/postman'
URL 8/postman[post]: request data = {"value":"value"}
URL 8/postman[post]: response data = {"req": {"value": "value"}}