当前位置: 首页 > 知识库问答 >
问题:

使用自定义JAAS登录模块启动JMX代理,将login()设置为始终返回true

谢鸿
2023-03-14

我正在为一个JMX实例构建一个定制的JAAS模块。正在运行的文件如下:

package com.this.mbean;

public interface ImplementationMBean {

    public void setName(String name);
    public String getName();

    public void setNumber(int number);
    public int getNumber();
    public boolean getKilled();
    public void setKilled(boolean killed);
}
package com.test.mbean;

    public class Implementation implements ImplementationMBean {

        private String name ;
        private int number;
        private boolean killed = false;

        public Implementation(String name, int number) {
            this.name = name;
            this.number = number;
        }

        @Override
        public void setName(String name) {
            this.name = name;

        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public void setNumber(int number) {
            this.number = number;
        }

        @Override
        public int getNumber() {
            return number;
        }

        @Override
        public boolean getKilled() {
            return killed;
        }

        @Override
        public void setKilled(boolean killed) {
            this.killed = killed;

        }

    }
package com.test.running;

import java.lang.management.ManagementFactory;
import com.test.mbean.*;

import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;

public class RunningImplementation {

    public static final String name = "defaultName";
    public static final int number = 100;

    public static void main(String[] args) 
            throws MalformedObjectNameException, InterruptedException, 
            InstanceAlreadyExistsException, MBeanRegistrationException, 
            NotCompliantMBeanException{

        //get MBean Server
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        //register MBean
        ImplementationMBean mBean = new Implementation(name, number);
        ObjectName name = new ObjectName("com.bard.mbean:type=ConcreteImplementation");

        mbs.registerMBean(mBean, name);

        do{
            Thread.sleep(1000);
            System.out.println("Name = " + mBean.getName() + ", number = " + mBean.getNumber());
        }while(mBean.getKilled() == false);

    }
}

这被打包到一个名为MBeanSecure.JAR的JAR文件中。

我已使用以下功能启用jmx代理:

-Dcom.sun.management.jmxremote

我已经将它设置为在本地主机的端口1234上运行:

-Dcom.sun.management.jmxremote.port=1234

我已将JMX代理配置为使用指定的JAAS配置条目:

-Dcom.sun.management.login.config=Sample

并指定了 Jaas 配置文件的路径:

-Djava.security.auth.login.config=sample_jaas.config
Sample {
   sample.module.SampleLoginModule required debug=true;
   authIdentity=monitorRole;
};

监视器角色在jmxremote.access中指定

-Dcom.sun.management.jmxremote.access.file=jmxremote.access

看起来像这样:

monitorRole readonly
controleRole readwrite

我的Loginmodule很简单,它返回truewhatever。

package sample.module;

import java.util.*;
import java.io.IOException;
import javax.security.auth.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;
import javax.security.auth.spi.*;
import sample.principal.SamplePrincipal;

public class SampleLoginModule implements LoginModule {

    // initial state
    private Subject subject;
    private CallbackHandler callbackHandler;
    private Map sharedState;
    private Map options;

    // configurable option
    private boolean debug = false;

    // the authentication status
    private boolean succeeded = false;
    private boolean commitSucceeded = false;

    // username and password
    private String username;
    private char[] password;

    // testUser's SamplePrincipal
    private SamplePrincipal userPrincipal;

    public void initialize(Subject subject, CallbackHandler callbackHandler,
            Map sharedState, Map options) {

        this.subject = subject;
        this.callbackHandler = callbackHandler;
        this.sharedState = sharedState;
        this.options = options;

        // initialize any configured options
        debug = "true".equalsIgnoreCase((String)options.get("debug"));
    }

    public boolean login() throws LoginException {
        return true;
    }

    public boolean commit() throws LoginException {
        if (succeeded == false) {
            return false;
        } else {
            // add a Principal (authenticated identity)
            // to the Subject

            // assume the user we authenticated is the SamplePrincipal
            userPrincipal = new SamplePrincipal(username);
            if (!subject.getPrincipals().contains(userPrincipal))
                subject.getPrincipals().add(userPrincipal);

            if (debug) {
                System.out.println("\t\t[SampleLoginModule] " +
                    "added SamplePrincipal to Subject");
            }

            // in any case, clean out state
            username = null;
            for (int i = 0; i < password.length; i++)
            password[i] = ' ';
            password = null;

            commitSucceeded = true;
            return true;
        }
    }

    public boolean abort() throws LoginException {
        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;
    }

    public boolean logout() throws LoginException {

        subject.getPrincipals().remove(userPrincipal);
        succeeded = false;
        succeeded = commitSucceeded;
        username = null;
        if (password != null) {
            for (int i = 0; i < password.length; i++)
            password[i] = ' ';
            password = null;
        }
        userPrincipal = null;
        return true;
    }
}

与主体类:

package sample.principal;

import java.security.Principal;

public class SamplePrincipal implements Principal, java.io.Serializable {

    private String name;


    public SamplePrincipal(String name) {
    if (name == null)
        throw new NullPointerException("illegal null input");

    this.name = name;
    }


    public String getName() {
    return name;
    }


    public String toString() {
    return("SamplePrincipal:  " + name);
    }


    public boolean equals(Object o) {
    if (o == null)
        return false;

        if (this == o)
            return true;

        if (!(o instanceof SamplePrincipal))
            return false;
        SamplePrincipal that = (SamplePrincipal)o;

    if (this.getName().equals(that.getName()))
        return true;
    return false;
    }


    public int hashCode() {
    return name.hashCode();
    }
}

当我使用以下命令运行代码时:

java -Dcom.sun.management.jmxremote.port=1234 -Dcom.sun.management.jmxremote.login.config=Sample -Dcom.java.security.auth.login.config=sample_jaas.config -Djava.security.policy==sampleazn.policy -Dcom.sun.management.jmxremote.access.file=jmxremote.access -jar MBeanSecure.jar

代码运行,定期输出

Name = defaultName, number = 100

然后,我尝试通过JConsole访问JMX代理

jconsole

这将打开Jconsole窗口,显示正在运行的进程。

然而,当我试图作为远程进程连接到它时,我得到一个连接失败的错误。这很难调试,因为我看不到任何日志显示这是失败的。我认为通过使用

com.sun.management.jmxremote.login.config

我覆盖默认登录行为?在这种情况下,它应该检查我的Jaas配置,运行loginmodule,它总是返回true,并允许指定monitorRole下的用户?

我相信错误在于配置文件,但是很难确认设置或调试,因为很少留档。

共有2个答案

董法
2023-03-14

我想修复这个代码中的错误。仅更改登录方法:

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.");
    }

新增:用户 = 新的 JMX 原则(名称);

还要注释commit()函数中的所有代码行,只需添加:

 subject.getPrincipals().add(user);
冷翼
2023-03-14

已解决:

我可以通过运行以下命令来调试问题:

jconsole -debug

这表明我的配置文件有语法错误,并且需要:

Sample {
   sample.module.SampleLoginModule required debug=true
   authIdentity=monitorRole;
};

代替

Sample {
   sample.module.SampleLoginModule required debug=true;
   authIdentity=monitorRole;
};

注意单个分号

 类似资料:
  • 我正在尝试开发一个定制的JAAS登录模块,它使用一个令牌并从不同的来源获取用户数据。它应该作为wildfly 8.2.1 final的身份验证领域。我有一个测试servlet,我想在其中进行身份验证,以便检查注入EJB的允许角色。 这个网站的测试:http://www.radcortez.com/custom-principal-and-loginmodule-for-wildfly/事实上,我甚

  • 有人可以使用jaas登录模块吗。我在看医生 我想是这些登录模块可以1.与OS用户进行身份验证2.提供该用户的组。 基本上我想通过操作系统进行身份验证。输入用户名和密码 我想用windows进行身份验证 我不想做LDAP认证只做os认证。 对于windows,有华夫饼干库可用。但我无法在使用64位机器时进行身份验证。在32位上运行良好。 对于linux,有jpam,但它不提供组。它只会检查用户名、密

  • 问题内容: 与使用控制台脚本保护的Kafka通信时出现问题。Kafka受保护,监听器受保护,机制由。 我做了什么:我尝试使用kafka脚本之一列出一些数据: 但是我明白了 命令失败,这是可以理解的,因为它由sasl保护。 因此,我尝试了如何向该命令添加客户端用户名/密码。首先,我尝试运行脚本,我曾经添加必要的文件。我很快发现我无法直接添加文件,我需要使用文件,所以我做到了。 我的属性文件(请记住,

  • 我正在尝试使用SP在OKTA(IdP)中使用我的Windows应用程序(SP)启动登录来设置SAML,但是在IDP验证我的凭据后,我收到了一个400错误的SAML请求。我没有重定向回应用程序URL(SP),而是收到了一个400错误的SAML请求。 我的SP URL-https://sampleapp.company.com/appname/default.aspx 我的SAML ACS URL-h

  • 在为EJB远程认证激活自定义登录模块时,还会调用applicationrealm进行身份验证。不幸的是,我不知道为什么。 EJB远程客户端属性: ejb URL: 基于普通standalone.xml的standalone.xml配置(不完整): 服务接口 自定义登录模块

  • 我正在开发一个带有spring security和基于注释的配置的代码。 但在从登录页访问WebSecurityConfig类(扩展了WebSecurityConfigurerAdapter)的configure方法中定义的登录处理url后,即使提供了正确的用户名和密码,它也总是重定向到httpSecurity的.FailureHandler()方法,而不是.SuccessHandler()方法。