GSSException createCredential

时间:2015-05-22 15:28:42

标签: java kerberos gssapi

主要编辑:2015-05-27:经过一定程度的成功更新了我目前所处的位置,而不是留下一个漫无边际的帖子....可能真的有些指针在这一点上 - 有点陷入困境......

我在Linux应用服务器(WebSphere)上运行一些需要对IIS Web服务进行身份验证的代码,该服务是为#34; Integrated Authentication"而配置的,但我有一些代码形成授权的问题:协商令牌。 我还应该说,我需要将此标记放入HTTP标头中,以便随后构建JAX-WS SOAP请求。我知道我的SOAP请求本身是有效的,因为我们之前使用的是WS-Security用户名令牌配置文件并且工作正常 - 尝试交换到kerberos很难......

我认为我的问题在于initSecContext。看起来在第一次调用时,上下文被配置在" some"方式并且有一些返回的令牌数据,但.isEstablished为false。我遇到的问题是将initSecContext调用放入循环 - 似乎IIS只是在我这样做时关闭连接。任何人都可以给我一些指示 - 我似乎采用了其他海报和Oracle样本所使用的方法(尽管IBM / WebSphere示例只进行了一次initSecContext调用并且没有检查.isEstablished这对我来说很奇怪在Oracle文档上。)

无论如何,我得到的错误在下面(注意Ready:属性似乎清楚地说initSecContext需要循环 - 至少对我来说);

[5/27/15 6:51:11:605 UTC] 0000004f SystemOut     O INFO: com.mycorp.kerberosKerberosTokenGenerator/getKerberosToken/run: After initSecContext:
--- GSSContext ---
        Owner:          domainuser@MYDOMAIN.COM
        Peer:           HTTP/iishost.mycorp.com
        State:          initialized
        Lifetime:       indefinite
        Ready:          no
        Flags:
                Confidentiality         off
                Delegation              on
                Integrity               off
                MutualAuthn             on
                ReplayDetection         off
                SequenceDetection       off
                DelegatedCred:          unknown
--- End of GSSContext ---

[5/27/15 6:51:11:605 UTC] 0000004f SystemOut     O INFO: com.mycorp.kerberosKerberosTokenGenerator/getKerberosToken/run: Context is not established, trying again
[5/27/15 6:51:11:606 UTC] 0000004f SystemOut     O ERROR: com.mycorp.kerberosKerberosTokenGenerator/getKerberosToken/run: IOException during context establishment: Connection reset

我的代码如下;

            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:http://www-01.ibm.com/support/knowledgecenter/SS7K4U_8.5.5/com.ibm.websphere.zseries.doc/ae/tsec_SPNEGO_token.html?cp=SS7K4U_8.5.5%2F1-3-0-20-4-0&lang=en

Oracle文档告诉我应该:https://docs.oracle.com/javase/7/docs/api/org/ietf/jgss/GSSContext.html

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

1 个答案:

答案 0 :(得分:1)

只是一个更新。我现在有这个工作 - 我以前的代码基本上没问题 - 只是我理解了如何将Kerberos令牌添加到JAX-WS请求中。事实证明,只需将Handler附加到bindingProvider即可。然后,处理程序获取Kerberos令牌并将其添加到请求的标头中 - 非常简单。

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

获得的处理程序链中
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;
    }

}