我对Java EE还是很陌生,在开始我要创建的应用程序上遇到很多麻烦。我想要的是一个连接到EJB项目的Swing应用程序客户端。我正在使用Glassfish v3.1.1。到目前为止,我有两个无状态的Bean,其中一个是使用@DeclareRoles和Glassfish中的JDBC领域来保护的,另一个是客户端的开始。
运行客户端时,您可以选择用户名,键入密码,然后登录。如果使用正确的密码,则一切正常(客户端控制台会吐出某些“安全”信息)。但是,如果键入错误的密码,则将您永久锁定。InitialContext.lookup不会再次调用CallbackHandler来检查新密码,而是继续使用不正确的凭据。
有人可以告诉我如何正确执行此操作吗?我是否在这种情况下使用了正确的方法- 网络上有大量信息,但基本上是0种我想做的事?一切似乎只适用于J2EE或Servlet!这是一些相关的代码。
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中?
<ior-security-config>
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); } } } }
现在,很长一段时间,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<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类。我从中删除了LoginCallbackHandler课程和参考application- client.xml。然后在登录代码中,在创建之前InitialContext,我使用了以下非常简单的两行代码:
ProgrammaticLogin
LoginCallbackHandler
application- client.xml
InitialContext
ProgrammaticLogin pl = new ProgrammaticLogin(); pl.login(usernameCombo.getSelectedItem().toString(), passwordText.getPassword());
不管我输入了错误的密码多少次,这似乎都是可行的(您也可以使用一个简单的计数器对此进行限制)。我花了这么长时间才弄清楚这一点,这有点愚蠢,但是该类没有出现在Netbeans中,所以我认为这在Java EE 6中已经不再有效。但是,这只是添加Glassfish/modules/security.jar到显示它的库。
Glassfish/modules/security.jar