Java EE 6应用程序客户端登录 [英] Java EE 6 Application Client login

查看:169
本文介绍了Java EE 6应用程序客户端登录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Java EE的新手,刚开始使用我想要创建的应用程序时遇到了很多麻烦。我想要的是连接到EJB项目的Swing应用程序客户端。我正在使用Glassfish v3.1.1。到目前为止我所拥有的是两个无状态bean,其中一个是使用@DeclareRoles和Glassfish中的JDBC域进行保护的,以及客户端的开头。

I am quite new to Java EE and have been having a lot of trouble just getting started on the application I want to create. What I would like is a Swing application client that connects to an EJB project. I am using Glassfish v3.1.1. What I have so far are two stateless beans, one of which is secured using @DeclareRoles and a JDBC realm in Glassfish, and the beginnings of a client.

当客户端运行后,您可以选择用户名,键入密码,然后登录。如果您使用正确的密码,一切正常(客户端控制台吐出一些安全信息)。但是,如果您输入的密码不正确,则会被永久锁定。 InitialContext.lookup不会再次调用CallbackHandler来检查新密码,它会继续使用不正确的凭据。

When the client is run, you are able to select a username, type a password, and thus login. If you use the correct password, everything works (the client console spits on some "secure" information). If you, however, type the incorrect password, you are permanently locked out. The InitialContext.lookup does not call the CallbackHandler again to check the new password, it continues using the incorrect credentials.

有人可以告诉我如何正确执行此操作吗?我是否在这种情况下使用了正确的方法 - 网上有大量的信息,但基本上我尝试做的是0个例子?一切似乎只适用于J2EE或Servlets!以下是一些相关代码。

Can someone please tell me how to do this correctly? Am I using the correct method for this situation - there is an enormous amount of info on the web but basically 0 examples of what I am trying to do? Everything seems to apply only to J2EE or Servlets! Here is some relevant code.

glassfish-ejb-jar.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-ejb-jar PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 EJB 3.1//EN" "http://glassfish.org/dtds/glassfish-ejb-jar_3_1-1.dtd">
<glassfish-ejb-jar>
  <security-role-mapping>
    <role-name>Admin</role-name>
    <group-name>Admin</group-name>
  </security-role-mapping>
  <security-role-mapping>
    <role-name>Employee</role-name>
    <group-name>Employee</group-name>
  </security-role-mapping>
  <enterprise-beans>
    <ejb>
      <ejb-name>LoginBean</ejb-name>
      <jndi-name>ejb/machineryhub/LoginService</jndi-name>
    </ejb>
    <ejb>
      <ejb-name>EmployeeBean</ejb-name>
      <jndi-name>ejb/machineryhub/EmployeeService</jndi-name>
      <ior-security-config>
        <as-context>
          <auth_method>username_password</auth_method>
          <realm>machineryhub</realm>
          <required>true</required>
        </as-context>
      </ior-security-config>
    </ejb>
  </enterprise-beans>
</glassfish-ejb-jar>

我是否需要添加< ior-security-config> 阻止我创建的每个安全bean?

Will I need to add the <ior-security-config> block to every secured bean I create?

application-client.xml:

<?xml version="1.0" encoding="UTF-8"?>
<application-client version="6" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application-client_6.xsd">
  <display-name>MachineryHub</display-name>
  <ejb-ref>
    <ejb-ref-name>LoginBean</ejb-ref-name>
    <ejb-ref-type>Session</ejb-ref-type>
    <remote>machineryhub.service.LoginService</remote>
  </ejb-ref>
  <ejb-ref>
    <ejb-ref-name>EmployeeBean</ejb-ref-name>
    <ejb-ref-type>Session</ejb-ref-type>
    <remote>machineryhub.service.EmployeeService</remote>
  </ejb-ref>
  <callback-handler>machineryhub.LoginCallbackHandler</callback-handler>
</application-client>

machineryhub.LoginCallbackHandler:

public class LoginCallbackHandler implements CallbackHandler {

  @Override
  public void handle(Callback[] clbcks) throws IOException, UnsupportedCallbackException {
    LoginFrame l = LoginFrame.instance;
    for (Callback cb : clbcks) {
      if (cb instanceof NameCallback) {
        NameCallback ncb = (NameCallback) cb;
        ncb.setName(l.usernameCombo.getSelectedItem().toString());
      } else if (cb instanceof PasswordCallback) {
        PasswordCallback pcb = (PasswordCallback) cb;
        pcb.setPassword(l.passwordText.getPassword());
      } else {
        throw new UnsupportedCallbackException(cb);
      }
    }
  }
}

现在是长期的,应用程序客户端。

And now for the long one, the swing application client.

machineryhub.LoginFrame

public class LoginFrame extends JFrame implements ActionListener {

  public static LoginFrame instance;

  public static void main(String[] args) {
    // Handle uncaught exceptions in the main and Swing threads
    ExceptionHandler.registerExceptionHandler();

    SwingUtilities.invokeLater(new Runnable() {

      @Override
      public void run() {
        try {
          UIManager.setLookAndFeel(new SubstanceMistSilverLookAndFeel());
          JFrame.setDefaultLookAndFeelDecorated(true);
          JDialog.setDefaultLookAndFeelDecorated(true);
          (new LoginFrame()).setVisible(true);
        } catch (final Exception exception) {
          ExceptionHandler.handle(Thread.currentThread(), exception);
        }
      }
    });
  }
  public JComboBox usernameCombo;
  public JPasswordField passwordText;
  private JButton loginButton;

  public LoginFrame() {
    // Window Setup

    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setTitle("Login :: MachineryHub");
    this.setLocationRelativeTo(null);
    this.setIconImages(IconFactory.application_images);

    // Create GUI

    createGui();
    usernameCombo.requestFocusInWindow();
    LoginFrame.instance = this;
  }

  private void createGui() {
    // Content Pane
    final JPanel contentPanel = new JPanel();

    List<String> usernames = getLoginService().getUsernames();
    Collections.sort(usernames);
    usernameCombo = new JComboBox(usernames.toArray());
    passwordText = new JPasswordField(15);
    passwordText.setActionCommand("Login");
    passwordText.addActionListener(this);

    loginButton = new JButton("Login", IconFactory.getImageIcon(IconFactory.Icon.KEY, 16));
    loginButton.setActionCommand("Login");
    loginButton.addActionListener(this);

    GroupLayout layout = new GroupLayout(contentPanel);
    contentPanel.setLayout(layout);
    layout.setAutoCreateContainerGaps(true);
    layout.setAutoCreateGaps(true);

    layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(usernameCombo).addGroup(layout.createSequentialGroup().addComponent(passwordText).addComponent(loginButton)));

    layout.setVerticalGroup(layout.createSequentialGroup().addComponent(usernameCombo, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE).addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(passwordText).addComponent(loginButton)));

    this.setContentPane(contentPanel);
    this.pack();
  }

  @Override
  public void actionPerformed(final ActionEvent e) {
    if (e == null || e.getActionCommand() == null) {
      return;
    }

    if (e.getActionCommand().equals("Login")) {
      loginButton.setEnabled(false);
      passwordText.setEnabled(false);
      usernameCombo.setEnabled(false);
      loginButton.setIcon(IconFactory.getImageIcon(IconFactory.SpecialImage.LOADING));

      try {
        Context c = new InitialContext();

        EmployeeService es = (EmployeeService) c.lookup("ejb/machineryhub/EmployeeService");
        System.out.println("Number of employees: " + es.getAllEmployees().size());
        this.dispose();
      } catch (NamingException exception) {
        loginButton.setEnabled(true);
        passwordText.setEnabled(true);
        usernameCombo.setEnabled(true);
        loginButton.setIcon(IconFactory.getImageIcon(IconFactory.Icon.KEY, 16));
        JOptionPane.showMessageDialog(LoginFrame.this, "Login Error: " + exception.getMessage(), "Login Error! :: MachineryHub", JOptionPane.ERROR_MESSAGE);
      }
    }
  }

  private LoginService getLoginService() {
    try {
      Context c = new InitialContext();
      return (LoginService) c.lookup("ejb/machineryhub/LoginService");
    } catch (NamingException ne) {
      throw new RuntimeException(ne);
    }
  }
}


推荐答案

我不肯定这是解决此问题的最佳推荐方式,但我找到了一种方法来完成我需要的工作。解决方案在于使用 ProgrammaticLogin 类。我从 application-client.xml 中删除​​了 LoginCallbackHandler 类和引用。然后在登录代码中,在创建 InitialContext 之前,我使用了以下非常简单的两行:

I'm not positive this is the best or recommended way to solve this problem, but I have found a way to do what I need. The solution lies in using the ProgrammaticLogin class. I removed the LoginCallbackHandler class and the reference from application-client.xml. Then in the login code, just before creating InitialContext, I used the following very simple two lines:

ProgrammaticLogin pl = new ProgrammaticLogin();
pl.login(usernameCombo.getSelectedItem().toString(), passwordText.getPassword());

无论我输入错误密码多少次,这似乎都有效(你可以设置一个限制)在这个以及一个简单的计数器)。我花了很长时间才弄清楚这一点感觉有点愚蠢,但是这个类并没有出现在Netbeans中,所以我认为它在Java EE 6中不再有效。但是,这只是添加 Glassfish / modules / security.jar 到库中以显示它。

And this seems to work regardless of how many times I enter the wrong password (you could put a limit on this as well with a simple counter). I feel a little stupid for taking so long to figure this out, but this class didn't show up in Netbeans so I assumed it was something that was no longer valid in Java EE 6. However, it is simply a matter of adding Glassfish/modules/security.jar to the libraries for it to show up.

这篇关于Java EE 6应用程序客户端登录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆