Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java GSSException创建凭据_Java_Kerberos_Gssapi - Fatal编程技术网

Java GSSException创建凭据

Java GSSException创建凭据,java,kerberos,gssapi,Java,Kerberos,Gssapi,主要编辑:2015-05-27:在取得一定程度的成功后,我更新了我目前的困境,而不是留下一篇杂乱无章的文章……这篇文章真的需要一些提示——有点陷入困境 我正在Linux应用服务器(WebSphere)上运行一些代码,需要对配置为“集成身份验证”的IIS web服务进行身份验证,但在形成授权时遇到一些问题:协商令牌。 我还应该说,我需要将这个令牌放入随后构建的JAX-WSSOAP请求的HTTP头中。我知道我的SOAP请求本身是有效的,因为我们以前使用的是WS-Security用户名令牌配置文件,它

主要编辑:2015-05-27:在取得一定程度的成功后,我更新了我目前的困境,而不是留下一篇杂乱无章的文章……这篇文章真的需要一些提示——有点陷入困境

我正在Linux应用服务器(WebSphere)上运行一些代码,需要对配置为“集成身份验证”的IIS web服务进行身份验证,但在形成授权时遇到一些问题:协商令牌。 我还应该说,我需要将这个令牌放入随后构建的JAX-WSSOAP请求的HTTP头中。我知道我的SOAP请求本身是有效的,因为我们以前使用的是WS-Security用户名令牌配置文件,它工作得很好-尝试交换到kerberos被证明是困难的

我想我的问题是initSecContext。似乎在第一次调用时,上下文是以“某种”方式配置的,并且有一些返回的令牌数据,但是.isEstablished为false。我遇到的问题是将initSecContext调用放入一个循环中-当我这样做时,IIS似乎只是关闭了连接。有人能给我一些建议吗?我似乎采用了其他海报和Oracle示例使用的方法(尽管IBM/WebSphere示例只进行了一次initSecContext调用,并且没有检查。isEstablished,这在Oracle文档中对我来说很奇怪)

无论如何,我得到的错误如下(注意Ready:property似乎明确表示initSecContext需要循环——至少对我来说是这样)

我的代码如下

            LoginContext lc = getLoginContext(contextName);
            final Subject subject = lc.getSubject();

            String b64Token = (String) Subject.doAs(subject, new PrivilegedExceptionAction() {
                @Override
                public Object run() throws PrivilegedActionException, GSSException {
                    // Create socket to server
                    Socket socket;
                    DataInputStream inStream = null;
                    DataOutputStream outStream = null;
                    try {
                        socket = new Socket("iishost.mycorp.com", 443);
                        inStream = new DataInputStream(socket.getInputStream());
                        outStream = new DataOutputStream(socket.getOutputStream());
                    } catch (IOException ex) {
                        System.out.println("Exception setting up server sockets: " + ex.getMessage());
                    }
                    GSSName gssName = manager.createName(userName, GSSName.NT_USER_NAME, KRB5_MECH_OID);
                    GSSCredential gssCred = manager.createCredential(gssName.canonicalize(KRB5_MECH_OID),
                            GSSCredential.DEFAULT_LIFETIME,
                            KRB5_MECH_OID,
                            GSSCredential.INITIATE_ONLY);

                    gssCred.add(gssName, GSSCredential.INDEFINITE_LIFETIME,
                            GSSCredential.INDEFINITE_LIFETIME,
                            SPNEGO_MECH_OID,
                            GSSCredential.INITIATE_ONLY);
                    GSSName gssServerName = manager.createName(servicePrincipal, KERBEROS_V5_PRINCIPAL_NAME);
                    GSSContext clientContext = manager.createContext(gssServerName.canonicalize(SPNEGO_MECH_OID),
                            SPNEGO_MECH_OID,
                            gssCred,
                            GSSContext.DEFAULT_LIFETIME);
                    clientContext.requestCredDeleg(true);
                    clientContext.requestMutualAuth(true);
                    byte[] token = new byte[0];

                    while (!clientContext.isEstablished()) {
                        try {
                            token = clientContext.initSecContext(token, 0, token.length);
// IF I LOOK AT token HERE THERE IS CERTAINLY TOKEN DATA THERE - .isEstablished IS STILL FALSE                          
                            outStream.writeInt(token.length);
                            outStream.write(token);
                            outStream.flush();

                            // Check if we're done
                            if (!clientContext.isEstablished()) {
                                token = new byte[inStream.readInt()];
                                inStream.readFully(token);
                            }
                        } catch (IOException ex) {

// THIS EXCEPTION IS THROWN ON SECOND ITERATION - LOOKS LIKE IIS CLOSES THE CONNECTION                      
                            System.out.println("IOException during context establishment: " + ex.getMessage());
                        }
                    }
                    String b64Token = Base64.encode(token);
                    clientContext.dispose();        // I'm assuming this won't invalidate the token in some way as I need to use it later
                    return b64Token;                
                }
            });
此文档告诉我不需要在initSecContext上循环,但是.isEstablished为我返回false:

Oracle文档告诉我应该:


我唯一犹豫不决的是,从Oracle文档来看,我似乎在启动应用程序对话,但我试图做的是只获取令牌&稍后在我的代码中,我将使用JAX-WS发布我的实际web服务调用(包括http头中的spnego/kerberos令牌)-这是我的问题的原因吗?

只是一个更新。我现在已经开始工作了——我以前的代码基本上还可以——这只是我对如何将Kerberos令牌添加到JAX-WS请求的理解。事实证明,这只是将处理程序附加到bindingProvider的问题。然后,处理程序获取Kerberos令牌并将其添加到请求的头中-nice和easy

下面是我的工作处理程序,它被添加到通过调用
bindingProvider.getBinding().getHandlerChain()获得的处理程序链中。

公共类HTTPKerberosHandler实现SOAPHandler{
私有最终字符串contextName;
私有最终字符串服务主体;
专用静态Oid KRB5_MECH_Oid=null;
专用静态Oid SPNEGO_MECH_Oid=null;
私有静态Oid KERBEROS_V5_主体_NAME=null;
最后一个字符串className=this.getClass().getName();
静止的{
试一试{
KERBEROS_V5_PRINCIPAL_NAME=新Oid(“1.2.840.113554.1.2.2.1”);
KRB5_MECH_OID=新OID(“1.2.840.113554.1.2.2”);
SPNEGO_MECH_OID=新OID(“1.3.6.1.5.5.2”);
}捕获(最终GSEX){
System.out.println(“创建mechOid的异常:+ex.getMessage());
例如printStackTrace();
}
}
公共HTTPKerberosHandler(最终字符串contextName,最终字符串servicePrincipal){
this.contextName=contextName;
this.servicePrincipal=servicePrincipal;
}
@凌驾
公共集getHeaders(){
返回null;
}
@凌驾
公共布尔handleFault(SOAPMessageContext上下文){
返回false;
}
@凌驾
公共无效关闭(MessageContext上下文){
//不采取行动
}
@凌驾
公共布尔handleMessage(SOAPMessageContext上下文){
if(((布尔)context.get(SOAPMessageContext.MESSAGE\u出站\u属性))){
返回HandlerRequest(上下文);
}否则{
返回HandlerResponse(上下文);
}
}
私有布尔HandlerRequest(SOAPMessageContext上下文){
byte[]标记=getKerberosToken(contextName,servicePrincipal);
HashMap sendTransportHeaders=新HashMap();
sendTransportHeaders.put(“授权”、“协商”+Base64.encode(令牌));
put(com.ibm.websphere.webservices.Constants.REQUEST\u TRANSPORT\u属性,sendTransportHeader);
返回true;
}
私有布尔HandlerResponse(SOAPMessageContext上下文){
logger.logInformation(类名,“HandlerResponse”,“检测到入站响应”);
返回true;
}
公共字节[]getKerberosToken(最终字符串contextName,最终字符串servicePrincipal){
试一试{
LoginContext lc=getLoginContext(contextName);
最终主题=lc.getSubject();
byte[]标记=(byte[])Subject.doAs(Subject,新PrivilegedExceptionAction(){
@凌驾
public Object run()引发PrivilegedActionException,gssexException{
最终字符串methodName=“getKerberosToken/run”;
最终的GSSManager管理器=GSSManager.getInstance();
Set principals=subject.getPrincipals();
迭代器it=principals.Iterator();
字符串principalName=((Principal)it.next()).getName();
logger.logInformation(className,methodName,“使用主体:[“+principalName+”]”);
GSSName GSSName=manager.createName(principalName、GSSName.NT\u用户名、KRB5\u机械OID);
GSSCredential gssCred=manager.createCredential(gssName.canonicalize(KRB5_MECH_OID)),
GSSCredential.DEFAULT_生命周期,
KRB5_机械类,
GSSCredential.仅启动_);
gssCred.add(gssName,GSSCredential.unlimited_寿命,
GSSCrede
            LoginContext lc = getLoginContext(contextName);
            final Subject subject = lc.getSubject();

            String b64Token = (String) Subject.doAs(subject, new PrivilegedExceptionAction() {
                @Override
                public Object run() throws PrivilegedActionException, GSSException {
                    // Create socket to server
                    Socket socket;
                    DataInputStream inStream = null;
                    DataOutputStream outStream = null;
                    try {
                        socket = new Socket("iishost.mycorp.com", 443);
                        inStream = new DataInputStream(socket.getInputStream());
                        outStream = new DataOutputStream(socket.getOutputStream());
                    } catch (IOException ex) {
                        System.out.println("Exception setting up server sockets: " + ex.getMessage());
                    }
                    GSSName gssName = manager.createName(userName, GSSName.NT_USER_NAME, KRB5_MECH_OID);
                    GSSCredential gssCred = manager.createCredential(gssName.canonicalize(KRB5_MECH_OID),
                            GSSCredential.DEFAULT_LIFETIME,
                            KRB5_MECH_OID,
                            GSSCredential.INITIATE_ONLY);

                    gssCred.add(gssName, GSSCredential.INDEFINITE_LIFETIME,
                            GSSCredential.INDEFINITE_LIFETIME,
                            SPNEGO_MECH_OID,
                            GSSCredential.INITIATE_ONLY);
                    GSSName gssServerName = manager.createName(servicePrincipal, KERBEROS_V5_PRINCIPAL_NAME);
                    GSSContext clientContext = manager.createContext(gssServerName.canonicalize(SPNEGO_MECH_OID),
                            SPNEGO_MECH_OID,
                            gssCred,
                            GSSContext.DEFAULT_LIFETIME);
                    clientContext.requestCredDeleg(true);
                    clientContext.requestMutualAuth(true);
                    byte[] token = new byte[0];

                    while (!clientContext.isEstablished()) {
                        try {
                            token = clientContext.initSecContext(token, 0, token.length);
// IF I LOOK AT token HERE THERE IS CERTAINLY TOKEN DATA THERE - .isEstablished IS STILL FALSE                          
                            outStream.writeInt(token.length);
                            outStream.write(token);
                            outStream.flush();

                            // Check if we're done
                            if (!clientContext.isEstablished()) {
                                token = new byte[inStream.readInt()];
                                inStream.readFully(token);
                            }
                        } catch (IOException ex) {

// THIS EXCEPTION IS THROWN ON SECOND ITERATION - LOOKS LIKE IIS CLOSES THE CONNECTION                      
                            System.out.println("IOException during context establishment: " + ex.getMessage());
                        }
                    }
                    String b64Token = Base64.encode(token);
                    clientContext.dispose();        // I'm assuming this won't invalidate the token in some way as I need to use it later
                    return b64Token;                
                }
            });
public class HTTPKerberosHandler implements SOAPHandler<SOAPMessageContext> {

    private final String contextName;
    private final String servicePrincipal;
    private static Oid KRB5_MECH_OID = null;
    private static Oid SPNEGO_MECH_OID = null;
    private static Oid KERBEROS_V5_PRINCIPAL_NAME = null;
    final String className = this.getClass().getName();

    static {
        try {
            KERBEROS_V5_PRINCIPAL_NAME = new Oid("1.2.840.113554.1.2.2.1");
            KRB5_MECH_OID = new Oid("1.2.840.113554.1.2.2");
            SPNEGO_MECH_OID = new Oid("1.3.6.1.5.5.2");
        } catch (final GSSException ex) {
            System.out.println("Exception creating mechOid's: " + ex.getMessage());
            ex.printStackTrace();
        }
    }

    public HTTPKerberosHandler(final String contextName, final String servicePrincipal) {
        this.contextName = contextName;
        this.servicePrincipal = servicePrincipal;
    }

    @Override
    public Set<QName> getHeaders() {
        return null;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        return false;
    }

    @Override
    public void close(MessageContext context) {
        // No action
    }

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        if (((Boolean) context.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY))) {
            return handleRequest(context);
        } else {
            return handleResponse(context);
        }
    }

    private boolean handleRequest(SOAPMessageContext context) {
        byte[] token = getKerberosToken(contextName, servicePrincipal);

        HashMap<String, String> sendTransportHeaders = new HashMap<String, String>();
        sendTransportHeaders.put("Authorization", "Negotiate " + Base64.encode(token));
        context.put(com.ibm.websphere.webservices.Constants.REQUEST_TRANSPORT_PROPERTIES, sendTransportHeaders);

        return true;
    }

    private boolean handleResponse(SOAPMessageContext context) {
        logger.logInformation(className, "handleResponse", "Inbound response detected");
        return true;
    }

    public byte[] getKerberosToken(final String contextName, final String servicePrincipal) {

        try {
            LoginContext lc = getLoginContext(contextName);

            final Subject subject = lc.getSubject();

            byte[] token = (byte[]) Subject.doAs(subject, new PrivilegedExceptionAction() {
                @Override
                public Object run() throws PrivilegedActionException, GSSException {
                    final String methodName = "getKerberosToken/run";
                    final GSSManager manager = GSSManager.getInstance();

                    Set<Principal> principals = subject.getPrincipals();
                    Iterator it = principals.iterator();
                    String principalName = ((Principal) it.next()).getName();
                    logger.logInformation(className, methodName, "Using principal: [" + principalName + "]");

                    GSSName gssName = manager.createName(principalName, GSSName.NT_USER_NAME, KRB5_MECH_OID);
                    GSSCredential gssCred = manager.createCredential(gssName.canonicalize(KRB5_MECH_OID),
                            GSSCredential.DEFAULT_LIFETIME,
                            KRB5_MECH_OID,
                            GSSCredential.INITIATE_ONLY);

                    gssCred.add(gssName, GSSCredential.INDEFINITE_LIFETIME,
                            GSSCredential.INDEFINITE_LIFETIME,
                            SPNEGO_MECH_OID,
                            GSSCredential.INITIATE_ONLY);
                    logger.logInformation(className, methodName, "Client TGT obtained: " + gssCred.toString());

                    GSSName gssServerName = manager.createName(servicePrincipal, GSSName.NT_USER_NAME);

                    GSSContext clientContext = manager.createContext(gssServerName.canonicalize(SPNEGO_MECH_OID),
                            SPNEGO_MECH_OID,
                            gssCred,
                            GSSContext.DEFAULT_LIFETIME);

                    logger.logInformation(className, methodName, "Service ticket obtained: " + clientContext.toString());

                    byte[] token = new byte[0];
                    token = clientContext.initSecContext(token, 0, token.length);
                    clientContext.dispose();
                    return token;
                }
            });

            return token;
        } catch (PrivilegedActionException ex) {
            logger.logError(HTTPKerberosHandler.class.getName(), methodName, "PrivilegedActionException: " + ex.getMessage());
        } catch (Exception ex) {
            logger.logError(HTTPKerberosHandler.class.getName(), methodName, "Exception: " + ex.getMessage());
        }

        return null;
    }

    private LoginContext getLoginContext(String contextName) {

        LoginContext lc = null;
        try {
            lc = new LoginContext(contextName);

            lc.login();
        } catch (LoginException le) {
            logger.logError(HTTPKerberosHandler.class.getName(), methodName, "Login exception: [" + le.getMessage() + "]");
            le.printStackTrace();
        }

        return lc;
    }

}