使用JAAS模块时如何使用mbean绕过jmx.access文件进行身份验证

时间:2015-08-10 07:35:44

标签: authentication jmx jaas mbeans

我在使用mbean身份验证时遇到了一个问题。问题是我需要始终更改我的mbean jmx.access文件以匹配不同用户的授权规则。不知何故,我需要绕过这个jmx.access文件并使用我自定义的JAAS登录模块进行身份验证,该模块只在后端调用其余的api。

请建议。 另外,为了做到这一点,任何其他方法都比这更好!

这是我的所有代码

package com.sigma.loginmodule;

import java.util.*;
import java.io.IOException;

import javax.management.remote.JMXPrincipal;
import javax.security.auth.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;
import javax.security.auth.spi.*;

import com.sigma.loginmodule.SamplePrincipal;

public class SampleLoginModule implements LoginModule {

    private Subject         subject;
    private CallbackHandler callbackHandler;
    private Map             sharedState;
    private Map             options;
    // configurable option
    private boolean         debug           = false;
    private boolean         succeeded       = false;

    private boolean         commitSucceeded = false;

    // username and password
    private String          username;
    private char[]          password;
    private JMXPrincipal    user;
    // testUser's SamplePrincipal
    private SamplePrincipal userPrincipal;

    public SampleLoginModule() {
        System.out.println("Login Module - constructor called");
    }

    public boolean abort() throws LoginException {
        System.out.println("Login Module - abort called");

        if (succeeded == false) {
            return false;
        } else if (succeeded == true && commitSucceeded == false) {
            // login succeeded but overall authentication failed
            succeeded = false;
            username = null;
            if (password != null) {
                for (int i = 0; i < password.length; i++)
                    password[i] = ' ';
                password = null;
            }
            userPrincipal = null;
        } else {
            // overall authentication succeeded and commit succeeded,
            // but someone else's commit failed
            logout();
        }
        return true;
        // return false;
    }

    public boolean commit() throws LoginException {
        System.out.println("Login Module - commit called");
        subject.getPrincipals().add(user);
        return succeeded;
    }

    public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
            Map<String, ?> options) {

        System.out.println("Login Module - initialize called");
        this.subject = subject;
        this.callbackHandler = callbackHandler;
        this.sharedState = sharedState;
        this.options = options;

        // System.out.println("testOption value: " + (String) options.get("testOption"));
        debug = "true".equalsIgnoreCase((String) options.get("debug"));

        succeeded = false;
    }

    public boolean login() throws LoginException {
        System.out.println("Login Module - login called");
        if (callbackHandler == null) {
            throw new LoginException("Oops, callbackHandler is null");
        }

        Callback[] callbacks = new Callback[2];
        callbacks[0] = new NameCallback("name:");
        callbacks[1] = new PasswordCallback("password:", false);

        try {
            callbackHandler.handle(callbacks);
        } catch (IOException e) {
            throw new LoginException("Oops, IOException calling handle on callbackHandler");
        } catch (UnsupportedCallbackException e) {
            throw new LoginException("Oops, UnsupportedCallbackException calling handle on callbackHandler");
        }

        NameCallback nameCallback = (NameCallback) callbacks[0];
        PasswordCallback passwordCallback = (PasswordCallback) callbacks[1];

        String name = nameCallback.getName();
        String password = new String(passwordCallback.getPassword());

        if ("sohanb".equals(name) && "welcome".equals(password)) {
            System.out.println("Success! You get to log in!");
            user = new JMXPrincipal(name);
            succeeded = true;
            return succeeded;
        } else {
            System.out.println("Failure! You don't get to log in");
            succeeded = false;
            throw new FailedLoginException("Sorry! No login for you.");
        }

        // return true;
    }

    public boolean logout() throws LoginException {
        System.out.println("Login Module - logout called");
        return false;
    }

}

}

JAAS登录模块

package client;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;



import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import com.sigma.SystemConfigMBean;


public class SystemConfigClient {

    public static final String HOST = "localhost";
    public static final String PORT = "8888";


    public static void main(String[] args) throws IOException, MalformedObjectNameException {
        JMXServiceURL url =
            new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + HOST + ":" + PORT + "/jmxrmi");
        //service:jmx:rmi:///jndi/rmi://localhost:8888/jmxrmi
        // for passing credentials for password
        Map<String, String[]> env = new HashMap<>();
        String[] credentials = { "sohanb", "welcome" };
        env.put(JMXConnector.CREDENTIALS, credentials);

        JMXConnector jmxConnector = JMXConnectorFactory.connect(url,env);
        MBeanServerConnection mbeanServerConnection = jmxConnector.getMBeanServerConnection();
        //ObjectName should be same as your MBean name
        ObjectName mbeanName = new ObjectName("com.sigma.jmx:type=SystemConfig");

        //Get MBean proxy instance that will be used to make calls to registered MBean
        SystemConfigMBean mbeanProxy =
            (SystemConfigMBean) MBeanServerInvocationHandler.newProxyInstance(
                mbeanServerConnection, mbeanName, SystemConfigMBean.class, true);

        //let's make some calls to mbean through proxy and see the results.
        System.out.println("Current SystemConfig::" + mbeanProxy.doConfig());

        String autenticate = RestClient.authenticate("handong", "welcome", true);
        System.out.println("Got autenticate Toekn id as " + autenticate);
        mbeanProxy.setToken(autenticate);
        mbeanProxy.setSchemaName("NewSchema");
        mbeanProxy.setThreadCount(5);

        System.out.println("New SystemConfig::" + mbeanProxy.doConfig());

        //let's terminate the mbean by making thread count as 0
      //  mbeanProxy.setThreadCount(0);

        //close the connection
        jmxConnector.close();
    }

}

JMX客户端代码:

Sample {
   com.sigma.loginmodule.SampleLoginModule required debug=true ;
};

示例JAAS文件:

JSONArray arr=new JSONArray(inputJson);
System.out.println(((JSONObject)arr.get(0)).get("attributionText"));

1 个答案:

答案 0 :(得分:0)

我只能看到解决这个问题的方法是编写自己的自定义JAAS验证程序,它实现了JMXAuthenticator。

用于身份验证的主要身份验证方法的代码段。 此方法调用调用我在JAAS身份验证器的构造函数中传递的登录模块,

 @SuppressWarnings("unchecked")
public final Subject authenticate(final Object credentials) throws SecurityException {
    Map<String, Object> myCredentials = new HashMap<String, Object>();

    if (credentials instanceof String[]) {
        // JConsole sends the credentials as string array
        // credentials[0] is the username
        // credentials[1] is the password
        String[] args = (String[]) credentials;

        if (args.length == 2) {

            myCredentials.put(USERNAME, args[0]);

            char[] pw = null;

            if (args[1] != null) {
                pw = args[1].toCharArray();
            }

            myCredentials.put(PASSWORD, pw);
        } else {
            throw new SecurityException();
        }
    } else if (credentials instanceof Map) {
        myCredentials.putAll((Map) credentials);
        if (sslEnabled && myCredentials.containsKey(CERTIFICATE)) {
            throw new SecurityException();
        }
    } else {
        throw new SecurityException();
    }

    LoginContext lc = null;

    try {
        lc = new LoginContext(systemName, new CredentialCallbackHandler(systemName, myCredentials));
        System.out.println("JAAS authenticator called ...");
    } catch (LoginException le) {
        le.printStackTrace();
    }

    try {
        lc.login();
        try {
            Subject.doAsPrivileged(lc.getSubject(), new PrintCodeBaseAndPrincipalsAction(), null);
        } catch (PrivilegedActionException ex) {
            if (ex.getException() instanceof SecurityException) {
                throw (SecurityException) ex.getException();
            } else {
                throw new SecurityException(ex.getException());
            }
        }

        return lc.getSubject();

    } catch (LoginException ex) {
        throw new SecurityException(ex);
    } catch (SecurityException ex) {
        throw ex;
    } catch (Throwable ex) {
        throw new SecurityException(ex);
    }    
}

以下是我调用和设置JAAS身份验证器构造函数的方法,

 Map<String, Object> env = new HashMap<String, Object>();
        JAASJMXAuthenticator authenticator = new JAASJMXAuthenticator(jaasConfigName, false);
        if (authenticator != null) {
            System.out.println("JAASJMXAuthenticator is not null");
            env.put(JMXConnectorServer.AUTHENTICATOR, authenticator);
        }

希望这有助于将来的某些人。如果被问到,我可以提供完整的代码示例。

干杯!