O erro desapareceu ao tentar fazer o login, só que a página que devia aparecer não aparece simplesmente processa e mantém na mesma página de login e limpa os campos. Fui ver na console e aparece o seguinte erro:
java.sql.SQLException: No value specified for parameter 1
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:127)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:95)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:1036)
at mz.com.SistemaArmazemFCSP.DAO.UsuarioDAO.obterUsuario(UsuarioDAO.java:47)
at mz.com.SistemaArmazemFCSP.Beans.LoginBean.login(LoginBean.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.el.parser.AstValue.invoke(AstValue.java:247)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:267)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(Unknown Source)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(Unknown Source)
at com.sun.faces.application.ActionListenerImpl.processAction(Unknown Source)
at javax.faces.component.UICommand.broadcast(Unknown Source)
at javax.faces.component.UIViewRoot.broadcastEvents(Unknown Source)
at javax.faces.component.UIViewRoot.processApplication(Unknown Source)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(Unknown Source)
at com.sun.faces.lifecycle.Phase.doPhase(Unknown Source)
at com.sun.faces.lifecycle.LifecycleImpl.execute(Unknown Source)
at javax.faces.webapp.FacesServlet.service(Unknown Source)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:494)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:651)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:412)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:754)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1385)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
Penso que seja no método DAO, certo? Fui confirmar mas não vi nenhum erro.
Aqui esta o método:
public Usuario obterUsuario(Usuario u) throws SQLException {
StringBuilder sql = new StringBuilder();
sql.append("Select * from usuario ");
sql.append("where usuario=? and senha=? ");
Connection conexao = Conexao.conectar();
PreparedStatement stmt = conexao.prepareStatement(sql.toString());
ResultSet resultado = stmt.executeQuery();
if (resultado.next()) {
u.setUsuario(resultado.getString("usuario"));
u.setSenha(resultado.getString("senha"));
return u;
} else {
return null;
}
}
O erro diz que não foi passado nenhum parametro para o sql.
Os seus parametros são os ‘=?’
Você tem que passar os valores para os parametros usuario e senha
Tipo assim:
PreparedStatement p = con.prepareStatement("select * from people where
(first_name = ? or last_name = ?) and address = ?");
p.setString(1, name);
p.setString(2, name);
p.setString(3, address);
Se quiser saber mais, procure por: PreparedStatement Parameters
Bem já consegui com uma ajuda efectuar o login, redirecionando consoante o nivel de acesso do usuario na base de dados. Mas o que falta é permitir criar sessao para cada usuario e a opção de terminar a sessao.
package mz.com.SistemaArmazemFCSP.Beans;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import mz.com.SistemaArmazemFCSP.DAO.FuncionarioDAO;
import mz.com.SistemaArmazemFCSP.DAO.UsuarioDAO;
import mz.com.SistemaArmazemFCSP.domain.Funcionario;
import mz.com.SistemaArmazemFCSP.domain.Usuario;
import mz.com.SistemaArmazemFCSP.util.Mensagens;
@ManagedBean(name = "MBLoginBean")
@SessionScoped
public class LoginBean implements Serializable {
public Usuario usuario = new Usuario();
public Funcionario funcionario = new Funcionario();
public ArrayList<Usuario> itens;
public ArrayList<Usuario> itensListados;
public ArrayList<Funcionario> itensFuncionario;
ExternalContext externalContext;
private static final long serialVersionUID = -31701307345516338L;
private static final Logger LOGGER = LoggerFactory.getLogger(Usuario.class);
public static final String HOME_PAGE_REDIRECT = "/login.xhtml?faces-redirect=true";
public static final String HOME_PAGE_ADMIN = "/indexAdmin.xhtml?faces-redirect=true";
public static final String HOME_PAGE_FUNCIONARIO = "/indexFuncionario.xhtml?faces-redirect=true";
public static final String HOME_PAGE_ADMINISTRADOR = "/indexAdministrador.xhtml?faces-redirect=true";
public static final String LOGOUT_PAGE_REDIRECT = "/login.xhtml?faces-redirect=true";
public Funcionario getFuncionario() {
return funcionario;
}
public ArrayList<Funcionario> getItensFuncionario() {
return itensFuncionario;
}
public void setItensFuncionario(ArrayList<Funcionario> itensFuncionario) {
this.itensFuncionario = itensFuncionario;
}
public void setFuncionario(Funcionario funcionario) {
this.funcionario = funcionario;
}
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
public ArrayList<Usuario> getItens() {
return itens;
}
public void setItens(ArrayList<Usuario> itens) {
this.itens = itens;
}
public ArrayList<Usuario> getItensListados() {
return itensListados;
}
public void setItensListados(ArrayList<Usuario> itensListados) {
this.itensListados = itensListados;
}
public void inserir() {
try {
UsuarioDAO udao = new UsuarioDAO();
udao.salvar(usuario);
itens = udao.listar();
Mensagens.adicionarMensagemSucesso("Salvo com sucesso");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void excluir() {
UsuarioDAO udao = new UsuarioDAO();
try {
udao.excluir(usuario);
itens = udao.listar();
Mensagens.adicionarMensagemSucesso("Excluído com sucesso");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void editar() {
try {
UsuarioDAO udao = new UsuarioDAO();
udao.editar(usuario);
itens= udao.listar();
Mensagens.adicionarMensagemSucesso("Editado com sucesso");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void prepararInserir() {
try {
usuario = new Usuario();
FuncionarioDAO fdao = new FuncionarioDAO();
itensFuncionario = fdao.listar();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void prepararEditar() {
try {
usuario = new Usuario();
FuncionarioDAO dfao = new FuncionarioDAO();
itensFuncionario = dfao.listar();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@PostConstruct
public void prepararPesquisa() {
try {
UsuarioDAO udao = new UsuarioDAO();
itens = udao.listar();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void prepararLogin() {
usuario = new Usuario();
}
public String login() {
Usuario usuarioRetornado = null;
UsuarioDAO udao = new UsuarioDAO();
try {
usuarioRetornado = udao.buscarUsuario(usuario.getUsuario(), usuario.getSenha());
} catch (SQLException e) {
e.printStackTrace();
}
System.out.println(usuarioRetornado.getUsuario());
if (usuarioRetornado.getRolestring().equals("Admin")) {
FacesContext.getCurrentInstance().getApplication().getNavigationHandler()
.handleNavigation(FacesContext.getCurrentInstance(), null, "indexAdmin.xhtml");
return HOME_PAGE_ADMIN;
} else if (usuarioRetornado.getRolestring().equals("Administrador")) {
FacesContext.getCurrentInstance().getApplication().getNavigationHandler()
.handleNavigation(FacesContext.getCurrentInstance(), null, "indexAdministrador.xhtml");
return HOME_PAGE_ADMINISTRADOR;
} else if (usuarioRetornado.getRolestring().equals("Funcionario")) {
FacesContext.getCurrentInstance().getApplication().getNavigationHandler()
.handleNavigation(FacesContext.getCurrentInstance(), null, "indexFuncionario.xhtml");
return HOME_PAGE_FUNCIONARIO;
} else {
return null;
}
}
No meu segundo post, eu falei como faz para adicionar na sessão.
Vou colar aqui a parte:
Basicamente, se você usa SessionScoped você já tem objetos/atributos na sessão
Para recuperar esses objetos/atributos de um bean SessionScoped, você pode usar a anotação @Inject do CDI ou @ManagedProperty do proprio JSF, mas CDI é recomendado.
O código abaixo utiliza @Named que é o @ManagedBean do CDI, e dentro da classe eu estou usando @Inject para pegar o bean de sessão que esta na memoria e o atribuindo na minha classe
PS:Não precisa de get e set pro MeuBeanDeSessao
@Named
@RequestScoped
public class SegundoBean {
@Inject
private MeuBeanDeSessao meuBeanDeSessao;
}
Ou então você pode adicionar o seu usuario na sessão (sem ser como um atributo do bean de sessão) depois de validar os dados de login.
Você esta fazendo um redirecionamento para uma página, só que mais abaixo você também faz através do return, usar as duas formas não faz muito sentido.
Não sei se você sabe, mas quando você chama um método no action, o retorno desse método diz ao JSF para qual página ele vai, no caso, você diz isso duas vezes.
É possível retornar null também, ai isso significa ficar na mesma página.
É bom também deixar o redirecionamento por último, caso você opte por usar handleNavigation, certifique de deixa-lo após adicionar o usuário na sessão.
O código que você postou faz três coisas:
Login
Adiciona o usuário na sessão
Redireciona para a página X
Você só vai pegar o usuário da sessão se for necessário na página X, do contrário você vai pegar só por pegar.
Mesmo que não tenha nada importante, é legal pegar pra Log do sistema. Então eu pegaria o usuário da sessão assim que o bean for criado, mas como fazer isso? Assim:
@PostConstruct
public void init() {
usuario = (Usuario) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("usuario");
}
O método anotado com @PostConstruct não pode lançar exceções, mas pode trata-las no catch.
O método anotado com @PostConstruct é executado após o bean ser criado.
Se o Bean for escopo de sessão, o método será executado em toda requisição feita a esse bean.
Obrigado entendi, bem isso seria do tipo pegar o usuario para não permitir entrar numa determinada pagina sem fazer o login?.. Estou precisando de adicionar o controlo de acesso nas paginas, porque facilmente qualquer um conseguira entrar numa pagina atraves do endereco isso nao deveria ser possivel porque nao tem seguranca nenhuma e com isso tera acesso a todos os dados. Como posso fazer para impedir isso? Na verdade vi em alguns tutoriais mas fiquei sem saber como implementar, porque nao resultava
Da uma olhada nesse tópico, eu mesmo postei como faz
PS: Pode ter uma coisa ou outra escrito de maneira errada, pois escrevi boa parte do código no próprio editor do GUJ
EDIT: É necessário fazer uma configuração extra no arquivo faces-config, que é referenciar o PhaseListener através do Fully Qualified Name da classe, ou seja, o pacote + nome da classe, segue o exemplo:
Bem tentei adptar o codigo que postaste no artigo que referenciaste acima no meu, mas na configuração dá erro e diz que não consegue encontrar o fully qualified name da classe. Abaixo deixo o codigo da classe e do arquivo faces-config.
package mz.com.SistemaArmazemFCSP.phaseListener;
import java.sql.SQLException;
import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import mz.com.SistemaArmazemFCSP.DAO.UsuarioDAO;
import mz.com.SistemaArmazemFCSP.domain.Usuario;
public class AutorizacaoPhaseListener implements PhaseListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private UsuarioDAO udao = new UsuarioDAO();
private Usuario usuario;
private FacesContext facesContext;
private NavigationHandler nh;
public FacesContext getFacesContext() {
return facesContext;
}
public void setFacesContext(FacesContext facesContext) {
this.facesContext = facesContext;
}
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
public UsuarioDAO getUdao() {
return udao;
}
public void setUdao(UsuarioDAO udao) {
this.udao = udao;
}
public NavigationHandler getNh() {
return nh;
}
public void setNh(NavigationHandler nh) {
this.nh = nh;
}
@Override
public void afterPhase(PhaseEvent event) {
facesContext = event.getFacesContext();
nh = facesContext.getApplication().getNavigationHandler();
Usuario usuario = (Usuario) facesContext.getExternalContext().getSessionMap().get("usuario");
String paginaActual = facesContext.getViewRoot().getViewId();
if (paginaActual.contains("/pages/*")) {
Usuario usuarioRetornado = null;
try {
usuarioRetornado = udao.buscarUsuario(usuario.getUsuario(), usuario.getSenha());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (usuarioRetornado == null) {
nh.handleNavigation(getFacesContext(), null, "index.xhtml?faces-redirect=true");
} else if (usuarioRetornado.getRolestring().equalsIgnoreCase("Admin")) {
nh.handleNavigation(getFacesContext(), null, "indexAdmin.xhtml?faces-redirect=true");
} else if (usuarioRetornado.getRolestring().equalsIgnoreCase("Administrador")) {
nh.handleNavigation(getFacesContext(), null, "indexAdministrador.xhtml?faces-redirect=true");
} else if (usuarioRetornado.getRolestring().equalsIgnoreCase("Funcionario")) {
nh.handleNavigation(getFacesContext(), null, "indexFuncionario.xhtml?faces-redirect=true");
}
} if (paginaActual.contains("/pages/index.xhtml?faces-redirect=true")) {
Usuario usuarioRetornado = null;
try {
usuarioRetornado = udao.buscarUsuario(usuario.getUsuario(), usuario.getSenha());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (usuarioRetornado == null) {
nh.handleNavigation(getFacesContext(), null, "/pages/index.xhtml?faces-redirect=true");
}
}
}
@Override
public void beforePhase(PhaseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public PhaseId getPhaseId() {
// TODO Auto-generated method stub
return null;
}
}
qual seria o endereço para puder englobar todas as paginas do projecto? A intenção seria aplicar em todas as paginas que o usuario apenas acessa ao fazer o login
Não sei se entendi bem, mas, as minhas paginas estão dentro de uma pasta que é "pages", então terei que criar uma outra pasta dentro da pasta "pages" que é a pasta "admin" e introduzir la todas as paginas que quero fazer controlo de acesso ou criar uma pasta para cada nivel de acesso de usuario e colocar as paginas que o usuario terá acesso.