Estou tentando implementar a parte de login com filter, mas estou esbarrado faz tempo já num problema.
Estou usando JSF 2.1 e Hibernate 3
Se alguém puder dar uma luz ai por favor
Mensagem de Erro:
GRAVE: 'org.hibernate.TransactionException' recebido ao invocar escuta de ação '#{loginBean.login}' para o componente 'loginButton'
GRAVE: org.hibernate.TransactionException: Transaction not successfully started
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:100)
at com.changes.dao.impl.UsuarioDaoImpl.isValidLoginAndPassword(UsuarioDaoImpl.java:40) //O primeiro ele mostra aqui
at com.changes.bean.LoginBean.login(LoginBean.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.el.parser.AstValue.invoke(AstValue.java:254)
at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:302)
at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:153)
at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:769)
at javax.faces.component.UICommand.broadcast(UICommand.java:300)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
at com.changes.util.AuthFilter.doFilter(AuthFilter.java:59)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
UsuarioDaoImpl
@Override
public boolean isValidLoginAndPassword(String login,String password) {
boolean valid;
Session session = HibernateUtil.getSessionFactory().openSession();
String sql = "select u from Usuario u where username=:user and password=:pass";
Query query = session.createQuery(sql);
query.setString("user", login);
query.setString("pass", password);
Usuario usr = (Usuario) query.uniqueResult();
valid = (usr != null);
session.getTransaction().commit(); //o erro é apontado aqui (já depurei e aqui não aparece nenhum valor...)
session.close();
return valid;
}
LoginBean
@ManagedBean(name="loginBean")
@SessionScoped
public class LoginBean {
private Usuario usuario;
private String user;
private String password;
public LoginBean() {
/*if (this.usuario == null) {
this.usuario = new Usuario();
}*/
}
public String login() {
UsuarioDao usuarioDao = new UsuarioDaoImpl();
if (usuarioDao.isValidLoginAndPassword(user, password)) {
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("user", "ok");
return "index.jsf";
} else {
return "reloadError";
}
}
public Usuario getUsuario() {
if (usuario == null){
usuario = new Usuario();
}
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
}
O problema acontece porque sua transação não foi iniciada: Transaction not successfully started.
Você abre sessão do hibernate e depois lá onde da o erro vc pede a transição: session.getTransaction().commit();
tente iniciar a transição logo depois de abrir a sessão:
Boa, passou… porém não está pegando o usuario e a senha.
Quando executo e digito o login e senha ele passa pelo select e para. E no deputador não vem valor nenhum.
Como posso fazer para pegar o valor digitado?
select
usuario0_.id as id1_,
usuario0_.perfil_id as perfil2_1_,
usuario0_.name as name1_,
usuario0_.email as email1_,
usuario0_.username as username1_,
usuario0_.password as password1_
from
changescontrol.usuario usuario0_
where
usuario0_.username=?
and usuario0_.password=?
UsuarioDaoImpl
public class UsuarioDaoImpl implements UsuarioDao {
@Override
public boolean isValidLoginAndPassword(String username,String password) {
boolean valid;
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Query query = session.createQuery("from Usuario usr where usr.username=:user and usr.password=:pass");
query.setString("user", username);
query.setString("pass", password);
Usuario usr = (Usuario) query.uniqueResult();
valid = (usr != null);
session.getTransaction().commit();
session.close();
return valid;
}
}
LoginBean
@ManagedBean(name="loginBean")
@SessionScoped
public class LoginBean {
private Usuario usuario;
private String user;
private String password;
public LoginBean() {
/*if (this.usuario == null) {
this.usuario = new Usuario();
}*/
}
public String login() {
UsuarioDao usuarioDao = new UsuarioDaoImpl();
if (usuarioDao.isValidLoginAndPassword(user, password)) {
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("user", "ok");
return "index.jsf";
} else {
return "reloadError";
}
}
public Usuario getUsuario() {
if (usuario == null){
usuario = new Usuario();
}
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
}
Essa SQL que mostra no console está certa, porém você não esta associando os inputText da página com as variáveis que você está usando no MB,
veja que você pede para o inputText ir para o campo username do usuário:
<h:inputText value="#{loginBean.usuario.username}"
id="username" required="true" label="username"/>
só que no LoginBean você não inicializa a variável usuario e o pior, você usa as variáveis user e password para tentar validar:
Eu alterei o método no dao e no bean para funcionar.
Eu consigo logar com usuario e senha q digito, mas o filter não está funcionando. Eu consigo ir direto para página index.jsf sendo que nao era pra deixar
Ou até mesmo se eu logo e depois volto para pagina de login e volto para index de novo, ele aceita … ou seja…nao está filtrando
Alguma ajuda?
loginBean
@ManagedBean(name="loginBean")
@SessionScoped
public class LoginBean {
private Usuario usuario;
public LoginBean() {
if (this.usuario == null) {
this.usuario = new Usuario();
}
}
public void redirecionar() throws IOException{
FacesContext faces = FacesContext.getCurrentInstance();
ExternalContext context = faces.getExternalContext();
context.redirect("/ControleChanges/index.jsf");
}
public void login(ActionEvent actionEvent) throws IOException {
RequestContext context = RequestContext.getCurrentInstance();
FacesMessage msg = null;
boolean loggedIn = false;
UsuarioDao usuarioDao = new UsuarioDaoImpl();
usuario = usuarioDao.buscarPorUsuario(usuario);
if (usuario != null) {
loggedIn = true;
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("user", "ok");
redirecionar();
msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Welcome", usuario.getUsername()); //"Usuario"
} else {
loggedIn = false;
msg = new FacesMessage(FacesMessage.SEVERITY_WARN, "Login Error", "Invalid credentials");
}
FacesContext.getCurrentInstance().addMessage(null, msg);
context.addCallbackParam("loggedIn", loggedIn);
}
public Usuario getUsuario() {
if (usuario == null){
usuario = new Usuario();
}
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
}
UsuarioDaoImpl
public class UsuarioDaoImpl implements UsuarioDao {
@Override
public Usuario buscarPorUsuario(Usuario usuario) {
Session session = HibernateUtil.getSessionFactory().openSession();
String sql = "select u from Usuario u where username=:user and password=:pass";
Query query = session.createQuery(sql);
query.setString("user", usuario.getUsername());
query.setString("pass", usuario.getPassword());
return (Usuario) query.uniqueResult();
}
}
Você configurou o web.xml para fazer a filtragem das páginas?
Essa configuração de impedir que acesse tais páginas fica no web.xml, onde você informa que todas páginas da pasta “x” só podem ser acessadas se logadas, e as páginas da raiz ou de oEutras pastas estão livres
Normalmente eu configuro para as páginas que estão na raiz do webcontent para serem acessíveis sem login, coloco então na raiz o index e o login, mas todas as outras páginas fica dentro de /pages, e defino que o usuário tem que logar para acessá-las, veja exemplo dessa configuração:
Só uma dica, crie uma classe que represente um usuário não logado ao invés de deixar como null, isso pode gerar algumas confusões como no retorno de getAttribute de HttpSession:
Aqui você passa a ter duas possibilidades de um retorno null, o objeto sendo null ou a não for encontrado um objeto com esse nome, a ainda o problema de depender da implementação interna de HttpSession que pode criar uma cópia do objeto ou copiar a instância em si, se HttpSession cria e guarda uma cópia do objeto uma instância null deixa de ser tratada como tal.
Pode ou não ser o caso, por conta da implementação interna, um exemplo para facilitar o entendimento do que estou dizendo:
[code]static class Car {
public String name;
public Car(String name) {
this.name = name;
}
public Car(Car other) {
if (other != null)
this.name = other.name;
}
}
public static void main(String[] args) {
Car c = null;
Car c2 = c; //cópia da instância
Car c3 = new Car(c); //cópida do objeto
if (c2 != null)
System.out.print("not ");
System.out.println("is null");
if (c3 != null)
System.out.print("not ");
System.out.println("is null");
}[/code]
[quote=rafa120]adicionei somente a parte de do web.xml e mesmo assim logo, mas o filtro ainda nao funciona
ja nem sei mais oq fazer[/quote]
Como seu problema é que a aplicação aceitar acessar as páginas que não era para deixar, analisei apenas o AuthFilter e o web.xml.
Primeiramente, com o url-pattern /* você exclue o CSS e ele não funcionará mesmo, por isso eu criei a pasta /pages para colocar as páginas da aplicação, deixando livre do filtre o CSS, página de login, imagens, etc.
O seu AuthFilter está correto, segue a mesma lógica do que tenho aqui em 5 aplicações funcionando perfeitamente.
Agora seu web.xml esta diferente no url-pattern que te falei, já apanhei muito tentando colocar todo webContent no filtro e sempre dava algum bug, depois que fiz a pasta pages para armazenar as páginas que necessitam de loguim os bugs foram embora…
Caso não queira criar a pasta “pages”, liste todas as páginas que você quer bloqueiar no url-pattern.