当前位置: 首页>>代码示例>>Python>>正文


Python RSAKey.serialize方法代码示例

本文整理汇总了Python中jwkest.jwk.RSAKey.serialize方法的典型用法代码示例。如果您正苦于以下问题:Python RSAKey.serialize方法的具体用法?Python RSAKey.serialize怎么用?Python RSAKey.serialize使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在jwkest.jwk.RSAKey的用法示例。


在下文中一共展示了RSAKey.serialize方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。

示例1: test_kspec

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
def test_kspec():
    _ckey = pem_cert2rsa(CERT)
    _jwk = RSAKey(key=_ckey)
    _jwk.serialize()

    print _jwk
    assert _jwk.kty == "RSA"
    assert _jwk.e == JWK["keys"][0]["e"]
    assert _jwk.n == JWK["keys"][0]["n"]
开发者ID:dv10den,项目名称:pyjwkest,代码行数:11,代码来源:test_0_jwk.py

示例2: test_extract_rsa_from_cert_2

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
def test_extract_rsa_from_cert_2():
    _ckey = pem_cert2rsa(CERT)
    _jwk = RSAKey(key=_ckey)
    _jwk.serialize()

    print _jwk

    _n = base64_to_long(str(_jwk.n))

    assert _ckey.n == _n
开发者ID:dv10den,项目名称:pyjwkest,代码行数:12,代码来源:test_0_jwk.py

示例3: generate_jwks

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
    def generate_jwks(self, mode):
        if "rotenc" in self.behavior_type:  # Rollover encryption keys
            rsa_key = RSAKey(kid="rotated_rsa_{}".format(time.time()),
                             use="enc").load_key(RSA.generate(2048))
            ec_key = ECKey(kid="rotated_ec_{}".format(time.time()),
                           use="enc").load_key(P256)

            keys = [rsa_key.serialize(private=True),
                    ec_key.serialize(private=True)]
            new_keys = {"keys": keys}
            #self.do_key_rollover(new_keys, "%d")

            signing_keys = [k.to_dict() for k in self.keyjar.get_signing_key()]
            new_keys["keys"].extend(signing_keys)
            return json.dumps(new_keys)
        elif "nokid1jwk" in self.behavior_type:
            alg = mode["sign_alg"]
            if not alg:
                alg = "RS256"
            keys = [k.to_dict() for kb in self.keyjar[""] for k in
                    list(kb.keys())]
            for key in keys:
                if key["use"] == "sig" and key["kty"].startswith(alg[:2]):
                    key.pop("kid", None)
                    jwk = dict(keys=[key])
                    return json.dumps(jwk)
            raise Exception(
                "Did not find sig {} key for nokid1jwk test ".format(alg))
        else:  # Return all keys
            keys = [k.to_dict() for kb in self.keyjar[""] for k in
                    list(kb.keys())]
            jwks = dict(keys=keys)
            return json.dumps(jwks)
开发者ID:rohe,项目名称:otest,代码行数:35,代码来源:provider.py

示例4: test_serialize_rsa_priv_key

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
def test_serialize_rsa_priv_key():
    rsakey = RSAKey(key=import_rsa_key_from_file(full_path("rsa.key")))
    assert rsakey.d

    d_rsakey = rsakey.serialize(private=True)
    restored_key = RSAKey(**d_rsakey)

    assert rsa_eq(restored_key, rsakey)
开发者ID:dallerbarn,项目名称:pyjwkest,代码行数:10,代码来源:test_2_jwk.py

示例5: test_kspec

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
def test_kspec():
    _ckey = pem_cert2rsa(CERT)
    _key = RSAKey()
    _key.load_key(_ckey)

    print(_key)
    jwk = _key.serialize()
    assert jwk["kty"] == "RSA"
    assert jwk["e"] == JWK["keys"][0]["e"].encode("utf-8")
    assert jwk["n"] == JWK["keys"][0]["n"].encode("utf-8")
开发者ID:dallerbarn,项目名称:pyjwkest,代码行数:12,代码来源:test_2_jwk.py

示例6: create_and_store_rsa_key_pair

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
def create_and_store_rsa_key_pair(name="pyoidc", path=".", size=1024):
    key = RSA.generate(size)

    keyfile = os.path.join(path, name)

    f = open("%s.key" % keyfile, "w")
    f.write(key.exportKey("PEM"))
    f.close()
    f = open("%s.pub" % keyfile, "w")
    f.write(key.publickey().exportKey("PEM"))
    f.close()

    rsa_key = RSAKey(key=key)
    rsa_key.serialize()
    # This will create JWK from the public RSA key
    jwk_spec = json.dumps(rsa_key.to_dict(), "enc")
    f = open(keyfile + ".jwk", "w")
    f.write(str(jwk_spec))
    f.close()

    return key
开发者ID:ahurtado-dj,项目名称:pyjwkest,代码行数:23,代码来源:jwk_create.py

示例7: id_token_as_signed_jwt

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
    def id_token_as_signed_jwt(self, session, loa="2", alg="", code=None,
                               access_token=None, user_info=None, auth_time=0,
                               exp=None, extra_claims=None, **kwargs):

        kwargs = {}

        if "rotsig" in self.behavior_type:  # Rollover signing keys
            if alg == "RS256":
                key = RSAKey(kid="rotated_rsa_{}".format(time.time()),
                             use="sig").load_key(RSA.generate(2048))
            else:  # alg == "ES256"
                key = ECKey(kid="rotated_ec_{}".format(time.time()),
                            use="sig").load_key(P256)

            new_keys = {"keys": [key.serialize(private=True)]}
            self.events.store("New signing keys", new_keys)
            self.do_key_rollover(new_keys, "%d")
            self.events.store("Rotated signing keys", '')

        if "nokid1jwks" in self.behavior_type:
            kwargs['keys'] = self.no_kid_keys()
            # found_key = None
            # for kb in self.keyjar.key_summary[""]:
            #     issuer_key = list(kb.keys())[0]
            #     if issuer_key.use == "sig" and \
            #             issuer_key.kty.startswith(
            #                 alg[:2]):
            #         issuer_key.kid = None
            #         found_key = key
            #         break
            # self.keyjar.key_summary[""] = [found_key]

        if "nokidmuljwks" in self.behavior_type:
            kwargs['keys'] = self.no_kid_keys()
            # for key in self.keyjar.key_summary[""]:
            #     for inner_key in list(key.keys()):
            #         inner_key.kid = None

        _jws = provider.Provider.id_token_as_signed_jwt(
            self, session, loa=loa, alg=alg, code=code,
            access_token=access_token, user_info=user_info,
            auth_time=auth_time,
            exp=exp, extra_claims=extra_claims, **kwargs)

        if "idts" in self.behavior_type:  # mess with the signature
            #
            p = _jws.split(".")
            p[2] = sort_string(p[2])
            _jws = ".".join(p)

        return _jws
开发者ID:rohe,项目名称:oidctest,代码行数:53,代码来源:provider.py

示例8: update

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
    def update(self, msg, state, key_size=0):
        """
        Used to 'update' the AccessToken Request

        :param msg:
        :param state: Used to map access token response to this request
        :param key_size:
        :return:
        """
        if not key_size:
            key_size = self.key_size

        key = RSAKey(key=RSA.generate(key_size))
        self.state2key[state] = key
        msg['key'] = json.dumps(key.serialize())
        return msg
开发者ID:Omosofe,项目名称:pyoidc,代码行数:18,代码来源:pop.py

示例9: usage

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
# - create a RSAKey object, and load the key with the load_key method
#
# A JWKS can instead be created as follow:
# - retrieve the rsa key
# - create a KEYS object and add the keys specifying the algorithm used for creation and the usage allowed for the key
#   (signature or encryption)
#
# A key jar can also be created with the method build_keyjar specifying a key_conf containing a list of keys to be
# created, with their type, name and usage (encryption of signature)

key = create_and_store_rsa_key_pair("foo", size=4096)
key2 = create_and_store_rsa_key_pair("foo2", size=4096)
rsa = RSAKey().load_key(key)

print "--- JWK ---"
print json.dumps(rsa.serialize(), sort_keys=True, indent=4, separators=(',', ': '))
print

########################################################

keys = KEYS()
keys.wrap_add(key, use="sig", kid="rsa1")
keys.wrap_add(key2, use="enc", kid="rsa1")

print "--- JWKS---"
print keys.dump_jwks()
print

########################################################

key_conf = [
开发者ID:biancini,项目名称:ojou_course,代码行数:33,代码来源:jwt_jwks.py

示例10: MetadataGeneration

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
class MetadataGeneration(object):

    def __init__(self, conf, key, idp_conf, xmlsec_path):
        """
        Constructor.
        Initiates the class.
        :param conf: Specific metadata conf
        :param key: A RSA key to be used for encryption.
        :param idp_conf: idp_conf see IdpProxy/idp_conf.example.py
        :param xmlsec_path:
        :raise:
        """
        if (conf is None) or (key is None):
            raise ValueError(
                "A new instance must include a value for logger, conf and key.")

        #Key to be used for encryption.
        self.key = RSAKey(key=key)
        self.key.serialize()
        self.alg = 'RSA-OAEP'
        self.enc = 'A128CBC-HS256'

        #Used for presentation of mako files.
        self.lookup = TemplateLookup(
            directories=[CONST_STATIC_MAKO + 'templates',
                         CONST_STATIC_MAKO + 'htdocs'],
            module_directory='modules',
            input_encoding='utf-8',
            output_encoding='utf-8')

        #A list of all social services used by this IdPproxy.
        self.social_service_key_list = []
        for key in conf:
            self.social_service_key_list.append(conf[key]["name"])

        #A list of all service providers used by this sp.
        self.sp_key_list = idp_conf.metadata.service_providers()

        self.xmlsec_path = xmlsec_path

    @staticmethod
    def verify_handle_request(path):
        """
        Verifies if the given path should be handled by this class.
        :param path: A path.
        :return: True if the path should be handled by this class, otherwise
            false.
        """
        return re.match(CONST_METADATA + ".*", path)

    @staticmethod
    def get_query_dict(environ):
        """
        Retrieves a dictionary with query parameters.
        :param environ: The wsgi enviroment.
        :return: A dictionary with query parameters.
        """
        qs = {}
        query = environ.get("QUERY_STRING", "")
        if not query:
            post_env = environ.copy()
            post_env['QUERY_STRING'] = ''
            query = cgi.FieldStorage(fp=environ['wsgi.input'], environ=post_env,
                                     keep_blank_values=True)
            if query is not None:
                try:
                    for item in query:
                        qs[query[item].name] = query[item].value
                except:
                    qs[CONST_BODY] = query.file.read()

        else:
            qs = dict((k, v if len(v) > 1 else v[0]) for k, v in
                      parse_qs(query).iteritems())
        return qs

    def handle_request(self, environ, start_response, path):
        """
        Call this method from the wsgi application.
        Handles the request if the path matched by verify_handle_request
        and any static file or CONST_METADATA or CONST_METADATASAVE.

        :param environ: wsgi enviroment
        :param start_response: the start response
        :param path: the requested path
        :return: a response fitted for wsgi application.
        """
        try:
            if path == CONST_METADATA:
                return self.handle_metadata(environ, start_response)
            elif path == CONST_METADATAVERIFY:
                return self.handle_metadata_verify(environ, start_response)
            elif path == CONST_METADATAVERIFYJSON:
                return self.handle_metadata_verify_json(
                    environ, start_response, self.get_query_dict(environ))
            elif path == CONST_METADATASAVE:
                return self.handle_metadata_save(environ, start_response,
                                                 self.get_query_dict(environ))
            else:
                filename = CONST_STATIC_FILE + self.get_static_file_name(path)
#.........这里部分代码省略.........
开发者ID:NORDUnet,项目名称:IdPproxy,代码行数:103,代码来源:secret.py

示例11: serialize_rsa_key

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
 def serialize_rsa_key(key):
     kid = hashlib.md5(key.encode('utf-8')).hexdigest()
     key = RSAKey(kid=kid, key=RSA.importKey(key), use='sig', alg='RS512')
     return key.serialize(private=False)
开发者ID:TeachAtTUM,项目名称:edx-platform,代码行数:6,代码来源:views.py

示例12: authorization_endpoint

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
    def authorization_endpoint(self, request="", cookie=None, **kwargs):
        _req = parse_qs(request)

        #self.events.store(EV_REQUEST, _req)

        try:
            _scope = _req["scope"]
        except KeyError:
            return self._error(
                error="incorrect_behavior",
                descr="No scope parameter"
            )
        else:
            # verify that openid is among the scopes
            _scopes = _scope[0].split(" ")
            if "openid" not in _scopes:
                return self._error(
                    error="incorrect_behavior",
                    descr="Scope does not contain 'openid'"
                )

        client_id = _req["client_id"][0]

        try:
            f = response_type_cmp(kwargs['test_cnf']['response_type'],
                                  _req['response_type'])
        except KeyError:
            pass
        else:
            if f is False:
                self.events.store(
                    EV_FAULT,
                    'Wrong response type: {}'.format(_req['response_type']))
                return self._error_response(error="incorrect_behavior",
                                            descr="Wrong response_type")

        _rtypes = []
        for rt in _req['response_type']:
            _rtypes.extend(rt.split(' '))

        if 'id_token' in _rtypes:
            try:
                self._update_client_keys(client_id)
            except TestError:
                return self._error(error="incorrect_behavior",
                                   descr="No change in client keys")

        _response = provider.Provider.authorization_endpoint(self, request,
                                                             cookie,
                                                             **kwargs)

        if "rotenc" in self.behavior_type:  # Rollover encryption keys
            rsa_key = RSAKey(kid="rotated_rsa_{}".format(time.time()),
                             use="enc").load_key(RSA.generate(2048))
            ec_key = ECKey(kid="rotated_ec_{}".format(time.time()),
                           use="enc").load_key(P256)

            keys = [rsa_key.serialize(private=True),
                    ec_key.serialize(private=True)]
            new_keys = {"keys": keys}
            self.events.store("New encryption keys", new_keys)
            self.do_key_rollover(new_keys, "%d")
            self.events.store("Rotated encryption keys", '')
            logger.info(
                'Rotated OP enc keys, new set: {}'.format(
                    key_summary(self.keyjar, '')))

        # This is just for logging purposes
        try:
            _resp = self.server.http_request(_req["request_uri"][0])
        except KeyError:
            pass
        else:
            if _resp.status_code == 200:
                self.events.store(EV_REQUEST,
                    "Request from request_uri: {}".format(_resp.text))

        return _response
开发者ID:selfissued,项目名称:oidctest,代码行数:80,代码来源:provider.py

示例13: create_and_store_rsa_key_pair

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
"""
import json
from oic.utils.keyio import create_and_store_rsa_key_pair
from oic.utils.keyio import build_keyjar
from jwkest.jwk import RSAKey
from jwkest.jwk import KEYS
from jwkest.jwk import keyitems2keyreps

# Will create 2 files on disc
# 'foo' will contain the private key
# 'foo.pub' will contain the public key
key = create_and_store_rsa_key_pair("foo", size=2048)

rsa = RSAKey().load_key(key)
# by default this will be the public part of the key
ser_rsa = rsa.serialize()

print("--- JWK (public) ----")
print(json.dumps(ser_rsa, sort_keys=True, indent=4, separators=(',', ': ')))
print()

# and this will give you the serialization of the private key
ser_rsa = rsa.serialize(private=True)

print("--- JWK (private) ----")
print(json.dumps(ser_rsa, sort_keys=True, indent=4, separators=(',', ': ')))
print()

# ============================================================================
# And now for the JWKS
开发者ID:biancini,项目名称:ojou_course,代码行数:32,代码来源:JWK_rsa.py

示例14: OpenIdConnectTestMixin

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
class OpenIdConnectTestMixin(object):
    """
    Mixin to test OpenID Connect consumers. Inheriting classes should also
    inherit OAuth2Test.
    """
    client_key = 'a-key'
    client_secret = 'a-secret-key'
    issuer = None  # id_token issuer
    openid_config_body = None
    key = None

    def setUp(self):
        super(OpenIdConnectTestMixin, self).setUp()
        test_root = os.path.dirname(os.path.dirname(__file__))
        self.key = RSAKey(kid='testkey').load(os.path.join(test_root, 'testkey.pem'))
        HTTPretty.register_uri(HTTPretty.GET,
          self.backend.OIDC_ENDPOINT + '/.well-known/openid-configuration',
          status=200,
          body=self.openid_config_body
        )
        oidc_config = json.loads(self.openid_config_body)

        def jwks(_request, _uri, headers):
            ks = KEYS()
            ks.add(self.key.serialize())
            return 200, headers, ks.dump_jwks()

        HTTPretty.register_uri(HTTPretty.GET,
                               oidc_config.get('jwks_uri'),
                               status=200,
                               body=jwks)

    def extra_settings(self):
        settings = super(OpenIdConnectTestMixin, self).extra_settings()
        settings.update({
            'SOCIAL_AUTH_{0}_KEY'.format(self.name): self.client_key,
            'SOCIAL_AUTH_{0}_SECRET'.format(self.name): self.client_secret,
            'SOCIAL_AUTH_{0}_ID_TOKEN_DECRYPTION_KEY'.format(self.name):
                self.client_secret
        })
        return settings

    def access_token_body(self, request, _url, headers):
        """
        Get the nonce from the request parameters, add it to the id_token, and
        return the complete response.
        """
        nonce = self.backend.data['nonce'].encode('utf-8')
        body = self.prepare_access_token_body(nonce=nonce)
        return 200, headers, body

    def get_id_token(self, client_key=None, expiration_datetime=None,
                     issue_datetime=None, nonce=None, issuer=None):
        """
        Return the id_token to be added to the access token body.
        """
        return {
            'iss': issuer,
            'nonce': nonce,
            'aud': client_key,
            'azp': client_key,
            'exp': expiration_datetime,
            'iat': issue_datetime,
            'sub': '1234'
        }

    def prepare_access_token_body(self, client_key=None, tamper_message=False,
                                  expiration_datetime=None,
                                  issue_datetime=None, nonce=None,
                                  issuer=None):
        """
        Prepares a provider access token response. Arguments:

        client_id       -- (str) OAuth ID for the client that requested
                                 authentication.
        expiration_time -- (datetime) Date and time after which the response
                                      should be considered invalid.
        """

        body = {'access_token': 'foobar', 'token_type': 'bearer'}
        client_key = client_key or self.client_key
        now = datetime.datetime.utcnow()
        expiration_datetime = expiration_datetime or \
                              (now + datetime.timedelta(seconds=30))
        issue_datetime = issue_datetime or now
        nonce = nonce or 'a-nonce'
        issuer = issuer or self.issuer
        id_token = self.get_id_token(
            client_key, timegm(expiration_datetime.utctimetuple()),
            timegm(issue_datetime.utctimetuple()), nonce, issuer)

        body['id_token'] = JWS(id_token, jwk=self.key, alg='RS256').sign_compact()
        if tamper_message:
            header, msg, sig = body['id_token'].split('.')
            id_token['sub'] = '1235'
            msg = b64encode_item(id_token).decode('utf-8')
            body['id_token'] = '.'.join([header, msg, sig])

        return json.dumps(body)

#.........这里部分代码省略.........
开发者ID:BeatrizFerreira,项目名称:EP1DAS,代码行数:103,代码来源:open_id_connect.py

示例15: authorization_endpoint

# 需要导入模块: from jwkest.jwk import RSAKey [as 别名]
# 或者: from jwkest.jwk.RSAKey import serialize [as 别名]
    def authorization_endpoint(self, request="", cookie=None, **kwargs):
        if isinstance(request, dict):
            _req = request
        else:
            _req = {}
            for key, val in parse_qs(request).items():
                if len(val) == 1:
                    _req[key] = val[0]
                else:
                    _req[key] = val

        # self.events.store(EV_REQUEST, _req)

        try:
            _scope = _req["scope"]
        except KeyError:
            return error_response(
                error="incorrect_behavior",
                descr="No scope parameter"
            )
        else:
            # verify that openid is among the scopes
            _scopes = _scope.split(" ")
            if "openid" not in _scopes:
                return error_response(
                    error="incorrect_behavior",
                    descr="Scope does not contain 'openid'"
                )

        client_id = _req["client_id"]

        try:
            f = response_type_cmp(self.capabilities['response_types_supported'],
                                  _req['response_type'])
        except KeyError:
            pass
        else:
            if f is False:
                self.events.store(
                    EV_FAULT,
                    'Wrong response type: {}'.format(_req['response_type']))
                return error_response(error="incorrect_behavior",
                                      descr="Not supported response_type")

        _rtypes = _req['response_type'].split(' ')

        if 'id_token' in _rtypes:
            try:
                self._update_client_keys(client_id)
            except TestError:
                return error_response(error="incorrect_behavior",
                                      descr="No change in client keys")

        if isinstance(request, dict):
            request = urlencode(request)

        if "max_age" in _req and _req["max_age"] == "0" and "prompt" in _req and _req["prompt"] == "none":
            aresp = {
                "error": "login_required",
            }
            if "state" in _req:
                aresp['state'] = _req["state"]

            return self.response_mode(_req, False,
                                      aresp=aresp,
                                      redirect_uri=_req['redirect_uri'],
                                      headers={})
        else:
            _response = provider.Provider.authorization_endpoint(self, request,
                                                                 cookie,
                                                                 **kwargs)

        if "rotenc" in self.behavior_type:  # Rollover encryption keys
            rsa_key = RSAKey(kid="rotated_rsa_{}".format(time.time()),
                             use="enc").load_key(RSA.generate(2048))
            ec_key = ECKey(kid="rotated_ec_{}".format(time.time()),
                           use="enc").load_key(P256)

            keys = [rsa_key.serialize(private=True),
                    ec_key.serialize(private=True)]
            new_keys = {"keys": keys}
            self.events.store("New encryption keys", new_keys)
            self.do_key_rollover(new_keys, "%d")
            self.events.store("Rotated encryption keys", '')
            logger.info(
                'Rotated OP enc keys, new set: {}'.format(
                    key_summary(self.keyjar, '')))

        # This is just for logging purposes
        try:
            _resp = self.server.http_request(_req["request_uri"])
        except KeyError:
            pass
        except requests.ConnectionError as err:
            self.events.store(EV_EXCEPTION, err)
            err = unwrap_exception(err)
            return error_response(error="server_error", descr=err)
        else:
            if _resp.status_code == 200:
                self.events.store(EV_REQUEST,
#.........这里部分代码省略.........
开发者ID:rohe,项目名称:oidctest,代码行数:103,代码来源:provider.py


注:本文中的jwkest.jwk.RSAKey.serialize方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。