Login do Cliente do Aplicativo Java EE 6

Eu sou bem novo no Java EE e tenho tido muitos problemas para começar a usar o aplicativo que desejo criar. O que eu gostaria é um cliente de aplicativo Swing que se conecte a um projeto EJB. Estou usando o Glassfish v3.1.1. O que eu tenho até agora são dois beans sem estado, um dos quais é protegido usando @DeclareRoles e um reino JDBC no Glassfish e o início de um cliente.

Quando o cliente é executado, você pode selecionar um nome de usuário, digitar uma senha e, assim, fazer o login. Se você usar a senha correta, tudo funcionará (o console do cliente cospe em algumas informações “seguras”). Se você, no entanto, digitar a senha incorreta, estará permanentemente bloqueado. O InitialContext.lookup não chama o CallbackHandler novamente para verificar a nova senha, ele continua usando as credenciais incorretas.

Alguém pode me dizer como fazer isso corretamente? Estou usando o método correto para essa situação? Há uma enorme quantidade de informações na Web, mas basicamente 0 exemplos do que estou tentando fazer? Tudo parece se aplicar apenas ao J2EE ou Servlets! Aqui está algum código relevante.

glassfish-ejb-jar.xml:

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

Eu precisarei adicionar o bloco a cada bean seguro que eu criar?

application-client.xml:

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

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

E agora, para o longo, o cliente do aplicativo 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); } } } 

Não estou certo de que este seja o melhor ou recomendado para resolver este problema, mas encontrei uma maneira de fazer o que preciso. A solução está em usar a class ProgrammaticLogin . Eu removi a class LoginCallbackHandler e a referência de application-client.xml . Em seguida, no código de login, pouco antes de criar o InitialContext , usei as seguintes duas linhas muito simples:

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

E isso parece funcionar, independentemente de quantas vezes eu digite a senha errada (você poderia colocar um limite sobre isso também com um contador simples). Eu me sinto um pouco idiota por ter demorado tanto para descobrir isso, mas essa class não apareceu no NetBeans, então eu assumi que era algo que não era mais válido no Java EE 6. No entanto, é simplesmente uma questão de adicionar o Glassfish/modules/security.jar para as bibliotecas para que ele apareça.

    Intereting Posts