• WS Security 认证方式详解


    本文参考文档如下:

    MSDN 官方详解 : http://www.microsoft.com/china/MSDN/library/WebServices/WebServices/HowASP.NETWebServicesWork.mspx?mfr=true

    WS安全规范说明 : https://www.oasis-open.org/committees/download.php/16782/wss-v1.1-spec-os-UsernameTokenProfile.pdf

    WS Security 一些历史信息 : http://zh.wikipedia.org/wiki/WS-Security

    如有不理解,请参考上面三个资源。

    WS-Security 所涉及的三个方面:身份验证、签名和加密

    1.身份验证

    常用的的三种认证方法:

    1.1用户名/密码

    在Apache CXF中,可以使用如下定义来使用用户名密码认证:

    客户端:

    <jaxws:client id="xxx" serviceClass="xxxy"
            address="xxx">
            
            <jaxws:outInterceptors>
                <bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
                    <constructor-arg>
                        <map>
                            <entry key="action" value="UsernameToken"/>
                            <entry key="user" value="xxx"/>
                            <!-- Password_Digest = Base64 ( SHA-1 ( nonce + created + password ) )  -->
                            <entry key="passwordType" value="PasswordDigest"/>
                            <entry key="passwordCallbackRef" value-ref="myPasswordCallback"/>
                        </map>
                    </constructor-arg>
                </bean>
            </jaxws:outInterceptors>
            
        </jaxws:client>

      以上的passwordType值为PasswordText时,则密码使用明文传输;为PasswordDigest时,则Password_Digest = Base64 ( SHA-1 ( nonce + created + password ) )

    比如传输的SOAP报文为:

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
        <soap:Header>
            <wsse:Security
                xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
                soap:mustUnderstand="1">
                <wsse:UsernameToken wsu:Id="UsernameToken-1">
                    <wsse:Username>xxx</wsse:Username>
                    <wsse:Password
                        Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">4t7Q2C0DnV21ie6ngsv6CwZ3vVw=</wsse:Password>
                    <wsse:Nonce
                        EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">R+6n+Z5L6FaG8IqeDrLGXw==</wsse:Nonce>
                    <wsu:Created>2014-04-21T09:56:51.361Z</wsu:Created>
                </wsse:UsernameToken>
            </wsse:Security>
        </soap:Header>
        <soap:Body>
            ......
        </soap:Body>
    </soap:Envelope>

      则上面计算的Password_Digest的参数则来源于wsse:Security下面的各个节点参数值。

    使用加密的密码传输,则客户端与服务端都需要指定一个passwordCallbackRef,该实现类继承CallbackHandler,下面做个示例

    public class ClientMyPasswordCallback implements CallbackHandler {
        
        private static final Log log = LogFactory.getLog(MyPasswordCallback.class);
        
        /* (non-Javadoc)
         * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
         */
        public void handle(Callback[] callbacks) throws IOException,
                UnsupportedCallbackException {
    
            WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
            
            pc.setPassword("xxx");
            
            
        }
        
    }

      服务端则使用:

    public class ServerMyPasswordCallback implements CallbackHandler {
        
        private static final Log log = LogFactory.getLog(MyPasswordCallback.class);
        
        /* (non-Javadoc)
         * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
         */
        public void handle(Callback[] callbacks) throws IOException,
                UnsupportedCallbackException {
    
            WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
            
        //通过数据库得到该用户名的密码,这里略去该过程
    String password = getPwdByUname(pc.getIdentifier());
      
    
            pc.setPassword(password );//直接设置从数据库得到的密码,WSS4J自动匹配该值与客户端传入的值,不需要调用pc.getPassword();因为它总是返回null
            
            
        }
        
    }

      服务端的拦截器中匹配密码方式是自动的,不需要从pc.getPassword()得到密码自己匹配,由于加密算法比较麻烦,所以省去这一步应该是比较好的设计

    X.509 证书与Kerberos则参考:

    http://www.microsoft.com/china/MSDN/library/WebServices/WebServices/HowASP.NETWebServicesWork.mspx?mfr=true

    文章里说明很清楚,不再重复。

    2.签名

    签名可以防止消息在传输中被篡改进行重复攻击等,可使用私钥对需要的部分进行签名,比如在上节的<身份认证>中,如果消息被截获,可导致重复攻击,

    需要对请求设置过期时间(wsu:Timestamp->wsu:Expires)并签名。

    3.消息包数据加密

    若传输的消息属于高安全级别,则需要使用X.509 证书对消息加密,即客户端使用服务端的公钥加密,服务端通过私钥解包,消息包只能在知道服务端私钥情况下才能解开。

    要对全部SOAP包加密,可启用SSL(通常为HTTPS)。

  • 相关阅读:
    socket套接字 struct模块
    网络编程 OSI七层协议
    内置方法 eval | exec 元类 单例
    选课系统
    iOS清理缓存 2016-04-19
    iOS 蓝牙 技术
    iOS人脸识别
    iOS 指纹识别
    极光推送的初步配置及其使用
    iOS 加急审核
  • 原文地址:https://www.cnblogs.com/mikevictor07/p/3678535.html
Copyright © 2020-2023  润新知