Java EE 6应用程序客户端登录

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

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

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

与GlassFish ejb-jar.xml中:

    Admin Admin   Employee Employee    LoginBean ejb/machineryhub/LoginService   EmployeeBean ejb/machineryhub/EmployeeService   username_password machineryhub true      

我是否需要将块添加到我创建的每个安全bean中?

应用client.xml的:

   MachineryHub  LoginBean Session machineryhub.service.LoginService   EmployeeBean Session machineryhub.service.EmployeeService  machineryhub.LoginCallbackHandler  

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

现在,对于漫长的一个,swing应用程序客户端。

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 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之前,我使用了以下非常简单的两行:

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

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