3

私は Java EE にまったく慣れていないので、作成したいアプリケーションを使い始めたばかりで、多くの問題を抱えています。私が欲しいのは、EJB プロジェクトに接続する Swing アプリケーション クライアントです。Glassfish v3.1.1 を使用しています。これまでのところ、2 つのステートレス Bean があり、そのうちの 1 つは @DeclareRoles と Glassfish の JDBC レルムを使用して保護されており、クライアントの始まりです。

クライアントを実行すると、ユーザー名を選択し、パスワードを入力してログインできます。正しいパスワードを使用すると、すべてが機能します (クライアント コンソールは「安全な」情報を吐き出します)。ただし、間違ったパスワードを入力すると、永久にロックアウトされます。InitialContext.lookup は、CallbackHandler を再度呼び出して新しいパスワードを確認することはなく、正しくない資格情報を使用し続けます。

誰かがこれを正しく行う方法を教えてもらえますか? この状況で正しい方法を使用していますか? Web には膨大な量の情報がありますが、基本的に私がやろうとしていることの例はありませんか? すべてが J2EE またはサーブレットにのみ適用されるようです! 関連するコードを次に示します。

グラスフィッシュ-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 にブロックを追加する必要がありますか?

アプリケーションクライアント.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>

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

では、最後に、swing アプリケーション クライアントについて説明します。

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

1 に答える 1

3

これがこの問題を解決する最良の方法または推奨される方法であるとは確信していませんが、必要なことを行う方法を見つけました。ProgrammaticLogin解決策は、クラスを使用することにあります。LoginCallbackHandlerからクラスと参照を削除しましたapplication-client.xml。次に、ログイン コードで、 を作成する直前にInitialContext、次の非常に単純な 2 行を使用しました。

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

そして、これは間違ったパスワードを何回入力しても機能するようです (単純なカウンターを使用して、これにも制限を設けることができます)。Glassfish/modules/security.jarこれを理解するのに時間がかかるのは少しばかげていると思いますが、このクラスは Netbeansには表示されなかったので、Java EE 6 では無効になったものだと思いました。それが表示されるライブラリ。

于 2011-10-07T15:37:21.160 に答える