楼主: justforregister

Java web services: Modeling and verifying WS-SecurityPolicy

[复制链接]
论坛徽章:
131
乌索普
日期:2017-09-26 13:06:30马上加薪
日期:2014-11-22 01:34:242014年世界杯参赛球队: 尼日利亚
日期:2014-06-17 15:23:23马上有对象
日期:2014-05-11 19:35:172014年新春福章
日期:2014-04-04 16:16:58马上有对象
日期:2014-03-08 16:50:54马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
21#
 楼主| 发表于 2011-5-31 00:09 | 只看该作者
The SymmetricBinding.AssertionHandler inner class defines the set of token roles defined for the <sp:SymmetricBinding> and also implements the VerificationHandler.complete() method to check that at least one type of token is present and no conflicting tokens are present. (<sp:SymmetricBinding> allows either an <sp:ProtectionToken>, with is used for both signing and encrypting messages, or separate <sp:EncryptionToken> and/or <sp:SignatureToken>s.)
BindingAssertionHandler, shown in Listing 5, is a common base for handling verification of all three types of binding assertions (transport, asymmetric, and symmetric). These each define one or more marker assertions, one or more token roles, a required <sp:AlgorithmSuite>, and an optional <sp:Layout> (the last two being assertions with child marker assertions but no nested policy).

使用道具 举报

回复
论坛徽章:
131
乌索普
日期:2017-09-26 13:06:30马上加薪
日期:2014-11-22 01:34:242014年世界杯参赛球队: 尼日利亚
日期:2014-06-17 15:23:23马上有对象
日期:2014-05-11 19:35:172014年新春福章
日期:2014-04-04 16:16:58马上有对象
日期:2014-03-08 16:50:54马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
22#
 楼主| 发表于 2011-5-31 00:10 | 只看该作者
Listing 5. BindingAssertionHandler
public class BindingAssertionHandler extends VerificationHandlerBase {    /** Names of marker elements allowed in <TransportBinding>. */    public static final Set<String> TRANSPORT_BINDING_MARKERS =        VerificationHandlerUtils.buildNameSet("IncludeTimestamp");        /** Names of marker elements allowed in ... or <SymmetricBinding>. */    public static final Set<String> ENCRYPTION_BINDING_MARKERS =        VerificationHandlerUtils.        buildNameSet("IncludeTimestamp|...|OnlySignEntireHeadersAndBody");        /** Actual element name. */    private final String m_elementName;        /** Roles allowed for tokens. */    private final Set<String> m_tokenRoles;        /** Token properties for binding. */    private final Map<String,TokenProperty> m_roleTokens;        /** Marker assertions allowed in policy. */    private final Set<String> m_knownMarkers;        /** Marker token assertions. */    private final Map<String,ExtensibleMarker> m_nameMarkers;    ...    protected BindingAssertionHandler(String name, Set<String> roles,        Set<String> markers) {        m_elementName = name;        m_tokenRoles = roles;        m_roleTokens = new HashMap<String,TokenProperty>();        m_knownMarkers = markers;        m_nameMarkers = new HashMap<String,ExtensibleMarker>();    }    ...    public void addMarker(ExtensibleMarker marker, ValidationContext vctx) {        String name = marker.getName();        if (m_knownMarkers.contains(name)) {            // generate warning for duplicate assertion            VerificationHandlerUtils.checkRepeat(marker, m_nameMarkers, vctx);        } else {            vctx.reportError("Assertion not allowed as child of sp:" + m_elementName,                marker);        }    }    public void addGeneral(AssertionBase asser, ValidationContext vctx) {        if (asser instanceof TokenProperty) {            TokenProperty token = (TokenProperty)asser;            String name = token.getName();            if (m_tokenRoles.contains(name)) {                TokenProperty prior = m_roleTokens.get(name);                if (prior == null) {                    m_roleTokens.put(name, token);                } else {                    vctx.reportError("Duplicate token ", asser);                }            } else {                vctx.reportError("Token not allowed as child of sp:" + m_elementName,                    asser);            }        } else if (asser instanceof AlgorithmSuite) {            ...        } else {            vctx.reportError("Assertion not allowed as child of sp:" + m_elementName,                asser);        }    }    public boolean complete(ValidationContext vctx) {        if (m_algorithmSuite == null) {            vctx.reportError("Missing required sp:AlgorithmSuite property", this);            return false;        } else {            return true;        }    }}

使用道具 举报

回复
论坛徽章:
131
乌索普
日期:2017-09-26 13:06:30马上加薪
日期:2014-11-22 01:34:242014年世界杯参赛球队: 尼日利亚
日期:2014-06-17 15:23:23马上有对象
日期:2014-05-11 19:35:172014年新春福章
日期:2014-04-04 16:16:58马上有对象
日期:2014-03-08 16:50:54马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
23#
 楼主| 发表于 2011-5-31 00:10 | 只看该作者
Both Listing 4 and Listing 5 use a VerificationHandlerUtils.buildNameSet() to construct a set of names from a string value. This method breaks the input string at | (pipe) characters to find the individual names to be added to the set, resulting in much more concise code than if the names were passed individually. The sets of names are then used to check assertions allowed in the nested policy.
Unmarshalling the model
The use of multiple namespaces with basically the same data creates some major problems for XML data binding. Most data binding tools could only deal with these multiple namespaces by creating separate sets of classes for each namespace. JiBX data binding can do better, by using multiple bindings to the same classes. Each binding can use the same element names for each class, but in a different namespace.
The loose structure of WS-Policy and WS-SecurityPolicy also causes problems for data binding, but here again JiBX can cleanly handle the data with a little added effort. JiBX supports user extension code for unmarshalling (and marshalling) data structures that otherwise cannot be bound to XML. I used several custom unmarshallers to handle the WS-Policy and WS-SecurityPolicy data. Probably the most interesting one is OperatorUnmarshaller, used to unmarshal any of the WS-Policy operators and their child assertions. Listing 6 shows the code for this unmarshaller:

使用道具 举报

回复
论坛徽章:
131
乌索普
日期:2017-09-26 13:06:30马上加薪
日期:2014-11-22 01:34:242014年世界杯参赛球队: 尼日利亚
日期:2014-06-17 15:23:23马上有对象
日期:2014-05-11 19:35:172014年新春福章
日期:2014-04-04 16:16:58马上有对象
日期:2014-03-08 16:50:54马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
24#
 楼主| 发表于 2011-5-31 00:10 | 只看该作者
Listing 6. OperatorUnmarshaller
public class OperatorUnmarshaller implements IUnmarshaller, IAliasable {    ...    public boolean isPresent(IUnmarshallingContext ictx) throws JiBXException {        UnmarshallingContext ctx = (UnmarshallingContext)ictx;        ctx.toTag();        if (PolicyNamespace.LOOKUP.getNamespace(ctx.getElementNamespace()) != null) {            String name = ctx.getElementName();            return "Policy".equals(name) || "ExactlyOne".equals(name) ||                "All".equals(name);        }        return false;    }        public Object unmarshal(Object obj, IUnmarshallingContext ictx) ... {        if (isPresent(ictx)) {            return unmarshalOperator((UnmarshallingContext)ictx);        } else {            return null;        }    }    private OperatorBase unmarshalOperator(UnmarshallingContext ctx) ... {                // create the instance to be returned        NamespaceInfo ns = PolicyNamespace.LOOKUP.            getNamespace(ctx.getElementNamespace());        if (ns == null) {            throw new IllegalStateException("Internal error - ...");        }        Policy policy = Policy.getNestedPolicy(ctx);        PolicyNamespace prior = policy == null ?            null : (PolicyNamespace)policy.checkNamespace(ns);        Policy policy = Policy.getNestedPolicy(ctx);        String name = ctx.getElementName();        OperatorBase operator;        if ("Policy".equals(name)) {            policy = new Policy(policy, ns);            operator = policy;        } else if ("ExactlyOne".equals(name)) {            operator = new OperatorBase.ExactlyOne(ns);        } else {            operator = new OperatorBase.All(ns);        }                // check for namespace conflict        if (prior != null && ns != prior) {            ((ValidationContext)ctx.getUserContext()).reportError("Policy namespace " +                ns.getUri() + " conflicts with containing policy namespace " +                prior.getUri(), operator);        }                // track object and handle all attributes        ctx.pushTrackedObject(operator);        operator.readAttributes(ctx);        ctx.nextToken();                // process all child elements        while (ctx.toTag() == IXMLReader.START_TAG) {            if (isPresent(ctx)) {                                // unmarshal child policy operator                operator.getChildOperators().add(unmarshalOperator(ctx));                            } else {                String uri = ctx.getElementNamespace();                name = ctx.getElementName();                IUnmarshaller unmarshaller = ctx.getUnmarshaller(uri, name);                if (unmarshaller == null) {                                        // treat unmapped element from known namespace as marker assertion                    ns = policy.getNamespace(uri);                    if (ns != null) {                        operator.getChildAssertions().add                            (ExtensibleMarkerUnmarshaller.unmarshal(ctx, ns));                    } else {                        // just use DOM for element from unknown namespace                        ...                    }                                    } else {                                        // unmarshal known child element as policy assertion                    Object object = unmarshaller.unmarshal(null, ctx);                    if (object instanceof AssertionBase) {                        operator.getChildAssertions().add((AssertionBase)object);                    } else {                        throw new JiBXException("Internal error - child element ...");                    }                                    }            }        }        ctx.nextToken();        ctx.popObject();        return operator;    }}

使用道具 举报

回复
论坛徽章:
131
乌索普
日期:2017-09-26 13:06:30马上加薪
日期:2014-11-22 01:34:242014年世界杯参赛球队: 尼日利亚
日期:2014-06-17 15:23:23马上有对象
日期:2014-05-11 19:35:172014年新春福章
日期:2014-04-04 16:16:58马上有对象
日期:2014-03-08 16:50:54马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
25#
 楼主| 发表于 2011-5-31 00:10 | 只看该作者
The IUnmarshaller interface only defines two methods: isPresent() to check if the current element start tag is handled by the unmarshaller, and unmarshal() to unmarshal the data from an element. In the Listing 6 code, the isPresent() method just checks if the current element namespace matches one of the WS-Policy versions, and then if the element name matches any of the three policy-operator names (Policy, ExactlyOne, or All).
The unmarshal() method is also simple, but only because it delegates all the work to the unmarshalOperator() method.  unmarshalOperator() assumes that you're positioned at one of the policy-operator elements, and starts by creating an instance of the matching operator class using the appropriate WS-Policy namespace (verifying that the namespace used on this operator matches that on the containing <wsp:Policy> element, if any). It then executes a loop to unmarshal all child elements. There are four ways of handling child elements:
  • If the child is another policy operator, recursively call unmarshalOperator().
  • If there's an unmarshaller for this element (meaning the binding definition contains a mapping definition for the element), call that unmarshaller.
  • If the element namespace is recognized as a policy-extension namespace, unmarshal as an empty marker assertion.
  • Otherwise, just treat as an unclassified extension element and use a DOM representation.

使用道具 举报

回复
论坛徽章:
131
乌索普
日期:2017-09-26 13:06:30马上加薪
日期:2014-11-22 01:34:242014年世界杯参赛球队: 尼日利亚
日期:2014-06-17 15:23:23马上有对象
日期:2014-05-11 19:35:172014年新春福章
日期:2014-04-04 16:16:58马上有对象
日期:2014-03-08 16:50:54马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
26#
 楼主| 发表于 2011-5-31 00:10 | 只看该作者
The third option means that marker elements don't need to be named in the JiBX binding definitions, which helps keep the bindings relatively simple (and also don't require individual classes, which keeps the data structures relatively simple). These bindings do need to define JiBX mapping definitions for all the nonmarker assertions, though, and separate bindings must be used for each namespace. Listing 7 shows the top-level binding, containing common abstract mappings (not associated with any element name, and hence reusable across namespaces) for both WS-Policy and WS-SecurityPolicy:

使用道具 举报

回复
论坛徽章:
131
乌索普
日期:2017-09-26 13:06:30马上加薪
日期:2014-11-22 01:34:242014年世界杯参赛球队: 尼日利亚
日期:2014-06-17 15:23:23马上有对象
日期:2014-05-11 19:35:172014年新春福章
日期:2014-04-04 16:16:58马上有对象
日期:2014-03-08 16:50:54马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
27#
 楼主| 发表于 2011-5-31 00:11 | 只看该作者
Listing 7. Top-level unmarshal binding definition
<binding package="com.sosnoski.ws" trim-whitespace="true"    value-style="attribute" force-classes="true" direction="input" track-source="true">    <include path="in-policy-200409.xml"/>  <include path="in-policy-200702.xml"/>  <include path="in-secpolicy-200507.xml"/>  <include path="in-secpolicy-200702.xml"/>    <!-- Base marker element mapping -->  <mapping class="com.sosnoski.ws.policy.ExtensibleMarker" unmarshaller=    "com.sosnoski.ws.secpolicy.SecurityPolicyNamespace$SecurityPolicyMarkerUnmarshaller"/>    <!-- Basic nested policy mapping -->  <mapping abstract="true" class="com.sosnoski.ws.secpolicy.NestedPolicy"      pre-set="preset" ordered="false" allow-repeats="true">    <structure set-method="setPolicy" usage="optional"        unmarshaller="com.sosnoski.ws.policy.OperatorUnmarshaller"/>    <structure type="org.w3c.dom.Element" unmarshaller="org.jibx.extras.DomElementMapper"        set-method="addExtension" usage="optional"/>  </mapping>  ...  <!-- Token base mapping -->  <mapping abstract="true" class="com.sosnoski.ws.secpolicy.TokenBase"      ordered="false" allow-repeats="true">    <structure map-as="com.sosnoski.ws.secpolicy.NestedPolicy"/>    <structure name="Issuer" set-method="setIssuer" usage="optional"         unmarshaller="com.sosnoski.ws.policy.ExtensibleValueUnmarshaller"/>    <structure name="IssuerName" set-method="setIssuerName" usage="optional"         unmarshaller="com.sosnoski.ws.policy.ExtensibleValueUnmarshaller"/>  </mapping>    <!-- Token property base mapping -->  <mapping abstract="true" class="com.sosnoski.ws.secpolicy.TokenProperty"      pre-set="preset" ordered="false" allow-repeats="true">    <structure map-as="com.sosnoski.ws.secpolicy.NestedPolicy"/>  </mapping>    <!-- Base handling for protection specifications -->  <mapping abstract="true" class="com.sosnoski.ws.secpolicy.ProtectParts"      pre-set="preset" ordered="false" allow-repeats="true">    <structure name="Body" set-method="setBody" usage="optional"        unmarshaller="com.sosnoski.ws.secpolicy.SecurityMarkerUnmarshaller"/>    <structure name="Attachments" set-method="setAttachments" usage="optional"        unmarshaller="com.sosnoski.ws.secpolicy.SecurityMarkerUnmarshaller"/>    <structure name="Header" set-method="addHeader" usage="optional"        unmarshaller="com.sosnoski.ws.secpolicy.Header$HeaderUnmarshaller"/>  </mapping>  </binding>

使用道具 举报

回复
论坛徽章:
131
乌索普
日期:2017-09-26 13:06:30马上加薪
日期:2014-11-22 01:34:242014年世界杯参赛球队: 尼日利亚
日期:2014-06-17 15:23:23马上有对象
日期:2014-05-11 19:35:172014年新春福章
日期:2014-04-04 16:16:58马上有对象
日期:2014-03-08 16:50:54马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
28#
 楼主| 发表于 2011-5-31 00:11 | 只看该作者
Listing 8 shows a pair of the namespace version-specific bindings referenced by <include> elements in the Listing 7 binding, one for a WS-Policy namespace and one for a WS-SecurityPolicy namespace. These associate the namespace version-independent data model classes with element names in a particular namespace, while either passing the handling on to specific unmarshaller classes (in the case of the WS-Policy operator elements, the Listing 6 OperatorUnmarshaller class) or delegating to one of the abstract mappings from the Listing 7 binding.

使用道具 举报

回复
论坛徽章:
131
乌索普
日期:2017-09-26 13:06:30马上加薪
日期:2014-11-22 01:34:242014年世界杯参赛球队: 尼日利亚
日期:2014-06-17 15:23:23马上有对象
日期:2014-05-11 19:35:172014年新春福章
日期:2014-04-04 16:16:58马上有对象
日期:2014-03-08 16:50:54马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
29#
 楼主| 发表于 2011-5-31 00:11 | 只看该作者
Listing 8. WS-Policy and WS-SecurityPolicy unmarshal binding definitions
<binding value-style="attribute" force-classes="true" direction="input"       track-source="true">  <!-- Make the recommendation namespace the default -->  <namespace uri="http://schemas.xmlsoap.org/ws/2004/09/policy"      default="elements" prefix="wsp"/>    <!-- Define all supported policy elements -->  <mapping name="Policy" class="com.sosnoski.ws.policy.Policy"      unmarshaller="com.sosnoski.ws.policy.OperatorUnmarshaller"/>  <mapping name="ExactlyOne" class="com.sosnoski.ws.policy.OperatorBase$ExactlyOne"      unmarshaller="com.sosnoski.ws.policy.OperatorUnmarshaller"/>  <mapping name="All" class="com.sosnoski.ws.policy.OperatorBase$All"      unmarshaller="com.sosnoski.ws.policy.OperatorUnmarshaller"/>  <mapping class="com.sosnoski.ws.policy.PolicyReference" name="PolicyReference">    <structure map-as="PolicyReference"/></mapping></binding><binding value-style="attribute" force-classes="true" direction="input"       track-source="true">  <!-- Make the WS-SecurityPolicy 1.1 namespace the default -->  <namespace uri="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"      default="elements" prefix="sp1"/>    <!-- Token variations -->  <mapping name="SecureConversationToken"       class="com.sosnoski.ws.secpolicy.SecureConversationToken">    <structure map-as="com.sosnoski.ws.secpolicy.TokenBase"/></mapping>  <mapping name="X509Token" class="com.sosnoski.ws.secpolicy.X509Token">    <structure map-as="com.sosnoski.ws.secpolicy.TokenBase"/></mapping>  ...  <!-- Token property variations -->  <mapping name="InitiatorToken"       class="com.sosnoski.ws.secpolicy.TokenProperty$InitiatorToken">    <structure map-as="com.sosnoski.ws.secpolicy.TokenProperty"/></mapping>  <mapping name="InitiatorSignatureToken"       class="com.sosnoski.ws.secpolicy.TokenProperty$InitiatorSignatureToken">    <structure map-as="com.sosnoski.ws.secpolicy.TokenProperty"/></mapping>  <mapping name="InitiatorEncryptionToken"       class="com.sosnoski.ws.secpolicy.TokenProperty$InitiatorEncryptionToken">    <structure map-as="com.sosnoski.ws.secpolicy.TokenProperty"/></mapping>  <mapping name="RecipientToken"       class="com.sosnoski.ws.secpolicy.TokenProperty$RecipientToken">    <structure map-as="com.sosnoski.ws.secpolicy.TokenProperty"/></mapping>  <mapping name="RecipientSignatureToken"       class="com.sosnoski.ws.secpolicy.TokenProperty$RecipientSignatureToken">    <structure map-as="com.sosnoski.ws.secpolicy.TokenProperty"/></mapping>  <mapping name="RecipientEncyrptionToken"       class="com.sosnoski.ws.secpolicy.TokenProperty$RecipientEncyrptionToken">    <structure map-as="com.sosnoski.ws.secpolicy.TokenProperty"/></mapping>  <mapping name="ProtectionToken"       class="com.sosnoski.ws.secpolicy.TokenProperty$ProtectionToken">    <structure map-as="com.sosnoski.ws.secpolicy.TokenProperty"/></mapping>  <mapping name="EncryptionToken"       class="com.sosnoski.ws.secpolicy.TokenProperty$EncryptionToken">    <structure map-as="com.sosnoski.ws.secpolicy.TokenProperty"/></mapping>  <mapping name="SignatureToken"       class="com.sosnoski.ws.secpolicy.TokenProperty$SignatureToken">    <structure map-as="com.sosnoski.ws.secpolicy.TokenProperty"/></mapping>  ...  <!-- Define other assertions containing nested policies -->  <mapping name="AlgorithmSuite" class="com.sosnoski.ws.secpolicy.AlgorithmSuite">    <structure map-as="com.sosnoski.ws.secpolicy.NestedPolicy"/></mapping>  <mapping name="AsymmetricBinding" class="com.sosnoski.ws.secpolicy.AsymmetricBinding">    <structure map-as="com.sosnoski.ws.secpolicy.NestedPolicy"/></mapping>  <mapping name="BootstrapPolicy" class="com.sosnoski.ws.secpolicy.BootstrapPolicy">    <structure map-as="com.sosnoski.ws.secpolicy.NestedPolicy"/></mapping>  <mapping name="Layout" class="com.sosnoski.ws.secpolicy.Layout">    <structure map-as="com.sosnoski.ws.secpolicy.NestedPolicy"/></mapping>  <mapping name="SymmetricBinding" class="com.sosnoski.ws.secpolicy.SymmetricBinding">    <structure map-as="com.sosnoski.ws.secpolicy.NestedPolicy"/></mapping>  <mapping name="Trust13" class="com.sosnoski.ws.secpolicy.Trust13">    <structure map-as="com.sosnoski.ws.secpolicy.NestedPolicy"/></mapping>  ...  <!-- Other elements with specific handling -->  <mapping name="SignedParts" class="com.sosnoski.ws.secpolicy.ProtectParts$SignedParts"      factory="com.sosnoski.ws.secpolicy.ProtectParts.newSignedParts">    <structure map-as="com.sosnoski.ws.secpolicy.ProtectParts"/></mapping>  <mapping name="EncryptedParts"       class="com.sosnoski.ws.secpolicy.ProtectParts$EncryptedParts"      factory="com.sosnoski.ws.secpolicy.ProtectParts.newEncryptedParts">    <structure map-as="com.sosnoski.ws.secpolicy.ProtectParts"/></mapping>  ...</binding>

使用道具 举报

回复
论坛徽章:
131
乌索普
日期:2017-09-26 13:06:30马上加薪
日期:2014-11-22 01:34:242014年世界杯参赛球队: 尼日利亚
日期:2014-06-17 15:23:23马上有对象
日期:2014-05-11 19:35:172014年新春福章
日期:2014-04-04 16:16:58马上有对象
日期:2014-03-08 16:50:54马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
30#
 楼主| 发表于 2011-5-31 00:11 | 只看该作者
Even with JiBX, a fair amount of complexity is involved in unmarshalling WS-Policy and WS-SecurityPolicy documents. But the combination of binding definitions with user extension code for unmarshalling makes the task much easier than would be the case with data binding tools that take a more rigid approach to handling XML.

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表