Spring Security 3 + facelets + JSF 2.0 problemas no login

Bom dia pessoal

Estou com um problema ao utilizar Spring security 3 + facelets na página de login de uma aplicação.
Quando uso o seguinte código o spring reconhece os campos usuário e senha.
Quando uso o código com facelets ele não reconhece. (Segue código no final do post)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <meta http-equiv="cache-control"   content="no-cache" />
        
    </h:head>
    <h:body >
        <p:dialog header="Login" visible="true" closable="false" draggable="false" resizable="false" width="420">
            
            <form action="j_spring_security_check" method="post">
                <h:panelGrid columns="2" cellpadding="5">
                    <h:outputLabel for="j_username" value="Username: *" />
                    <h:inputText id="j_username" required="true"/>
                    <h:outputLabel for="j_password" value="Password: * " />
                    <h:inputSecret id="j_password" required="true"/>
                    <h:commandButton value="Login"/>
                </h:panelGrid>
            </form>
        </p:dialog>
    </h:body>
</html>

Quando utilizo esse código o spring não autentica minha sessão.

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:p="http://primefaces.org/ui" template="template/layout.xhtml">

	<meta http-equiv="X-UA-Compatible" />
	<meta content='text/html; charset=UTF-8' http-equiv="Content-Type" />
	<meta http-equiv="Pragma" content="0" />

	<ui:define name="menu" />
	<ui:define name="content">
		<h:panelGroup id="content_area" />
		<p:growl autoUpdate="true" showDetail="true" />
		<p:dialog id="loginDialog" widgetVar="loginDialog" header="Login"
			visible="true" closable="false" draggable="true" resizable="false"
			modal="true" appendToBody="true" showEffect="fade" hideEffect="fade"
			width="320" style="font-size: 14px !important">
			<h:form id="loginForm" prependId="false">
				<br />
				<h:panelGrid columns="2" style="margin: auto !important">
					<h:outputLabel value="Usuário:" />
					<h:inputText id="j_username" required="true"
						requiredMessage="Entre com seu usuário" />
					<h:outputLabel value="Senha:" />
					<h:inputSecret id="j_password" required="true"
						requiredMessage="Entre com sua senha" />
				</h:panelGrid>
				<br />
				<p:commandButton value="Logar" action="/j_spring_security_check"
					style="float:right; font-size: 14px !important"
					update=":loginDialog"/>
				<br />
				
			</h:form>
		</p:dialog>
	</ui:define>
</ui:composition>

Alguém pode me ajudar por favor?

Obrigado

Como assim não reconhece? Cara, eu não entendo muito de jsf, mas entendo um pouquinho de spring security. No seu primeiro código você coloca na action do form [color=blue]“j_spring_security_check”[/color], e no segundo [color=blue]"/j_spring_security_check"[/color]. Confere?

A action do form fica no commandButton?! Não fica no form?

jaboot bom dia

então mudei a action para o form, mas o erro persiste.

Obrigado

E a barra?! Note que no seu primeiro código você coloca sem a barra, e no segundo tem uma barra antes do j_spring_security_check

Olá

Retirei a barra, executei a action no form, logo após no commandButton e nada.

Ele da um refresh no campo senha e não loga :cry:

Obrigado jaboot

Bom dia pessoal

Consegui resolver meu problema. Vou detalhar a resolução, caso alguém tenha o mesmo problema isso poderá ajudar.

Primeiramente eu alterei as versões dos *.jar do spring security.
Da versão 3.1.0 eu passei para a versão 3.0.2.

Ao alterar a versão dos jars será necessário alterar a versão do xsd no arquivo “applicationContext.xml”
Altere a versão para: "http://www.springframework.org/schema/security/spring-security-3.0.xsd">"

Será necessário criar 3 classes, elas serão exemplificadas abaixo:

import java.io.IOException;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

@ManagedBean(name="loginBean")
@SessionScoped
public class LoginBean {
    private String username;
    private String password;
    public LoginBean() {
    }
    public String doLogin() throws IOException, ServletException {
        ExternalContext context = FacesContext.getCurrentInstance()
                .getExternalContext();
        RequestDispatcher dispatcher = ((ServletRequest) context.getRequest())
                .getRequestDispatcher("/j_spring_security_check?j_username=" + username
                                + "&j_password=" + password);
        dispatcher.forward((ServletRequest) context.getRequest(),
                (ServletResponse) context.getResponse());
        FacesContext.getCurrentInstance().responseComplete();
        // It's OK to return null here because Faces is just going to exit.
        return null;
    }
    public String getPassword() {
        return password;
    }
    public String getUsername() {
        return username;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public void setUsername(String username) {
        this.username = username;
    }
}

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
public class FacesUtils {
    public static void addErrorMessage(String msg) {
        addMessage(FacesMessage.SEVERITY_ERROR, msg);
    }
    private static void addMessage(FacesMessage.Severity severity, String msg) {
        final FacesMessage facesMsg = new FacesMessage(severity, msg, msg);
        FacesContext.getCurrentInstance().addMessage(null, facesMsg);
    }
    public static void addSuccessMessage(String msg) {
        addMessage(FacesMessage.SEVERITY_INFO, msg);
    }
    public static String getBundleKey(String bundleName, String key) {
        return FacesContext
                .getCurrentInstance()
                .getApplication()
                .getResourceBundle(FacesContext.getCurrentInstance(),
                        bundleName).getString(key);
    }
}

import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;

import br.com.formattanegocios.util.FacesUtils;
public class LoginErrorPhaseListener implements PhaseListener
{
    private static final long serialVersionUID = -1216620620302322995L;
    @Override
    public void afterPhase(final PhaseEvent arg0)
    {}
    @Override
    public void beforePhase(final PhaseEvent arg0)
    {
        Exception e = (Exception) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(
                AbstractAuthenticationProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY);
        if (e instanceof BadCredentialsException)
        {
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(
                    AbstractAuthenticationProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY, null);
            FacesUtils.addErrorMessage("Username or password not valid.");
        }
    }
    @Override
    public PhaseId getPhaseId()
    {
        return PhaseId.RENDER_RESPONSE;
    }
}

Após a criação das classes será necessário alterar a página de login para que ela chame o managedBean “loginBean” na action do commandButton

Segue o exemplo:


<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core"%>
<%@ taglib prefix="c_rt" uri="http://java.sun.com/jstl/core_rt"%>
<%@ taglib prefix="f"  uri="http://java.sun.com/jsf/core"%>
<%@ taglib prefix="h"  uri="http://java.sun.com/jsf/html"%>
<html>
    <head>
        <title>Spring Security Login</title>
    </head>
    <body>
        <f:view >
            <h:form >
                <h:panelGrid columns="2">
                    <h:outputLabel value="User Name" for="j_username"/>
                    <h:inputText id="j_username"
                                   value="#{loginBean.username}"
                                   required="true"/>
                    <h:outputLabel value="Password" for="j_password"/>
                    <h:inputSecret id="j_password"
                                     value="#{loginBean.password}"
                                     required="true"/>
                </h:panelGrid>
                <h:commandButton action="#{loginBean.doLogin}" value="Login"/>
                <h:messages style="color: red;"/>
            </h:form>
        </f:view>
    </body>
</html>

Isso resolve o problema para utilização das tags do jsf/Facelets com spring Security.

Qualquer dúvida, estou a disposição

até mais

obrigado

Problema resolvido.

Resolução postada acima.

Obrigado

Olá javaTech, estou com o mesmo problema aqui preciso controlar meu login no spring via uma managed bean próprio tentei seguir sua solução mas quando tento fazer o login ele retorna erro HTTP Status 404.

Bom vou dizer o que quero fazer talvez você possa sugerir algo, é que preciso além da autenticação do login/usuário verificar também um Captcha (achei um solução com JCpathca, porém aqui eu utilizo o Simple Captcha)

desde já agradeço.

Bom dia

Erro 404 significa que a pagina que ele deve redirecionar após o sucesso/ Falha de login não existe.

Verifique seu arquivo applicationContext.xml e veja se as páginas realmente existem no seu projeto.

Veja como está meu applicationContext.xml

<http auto-config="false" access-denied-page="/publico/acessonegado.jsf">

	<intercept-url pattern="/admin/**" access="ROLE_ADMINISTRADOR" />
	<intercept-url pattern="/restrito/**" access="ROLE_USUARIO" />
	<intercept-url pattern="/cliente/**" access="ROLE_CLIENTE" />
	<intercept-url pattern="/funcionario/**" access="ROLE_FUNCIONARIO" />

	<form-login login-page="/publico/l.jsf"
		always-use-default-target="true" default-target-url="/restrito/index.jsf"
		authentication-failure-url="/publico/l.jsf?error=invalido" />
	<logout />
	<remember-me />
	
</http>

a página de l.xhtml está no diretório público e o index.xhtml dentro de restrito

ola javaTech

eu implementei do jeito que vc postou a cima, so que no meu caso ele não inicia o processo de validacao
vc poderia postar como ficou o seu applicationContext.xml

grato

[quote=andreluiz_sh]ola javaTech

eu implementei do jeito que vc postou a cima, so que no meu caso ele não inicia o processo de validacao
vc poderia postar como ficou o seu applicationContext.xml

grato[/quote]

Também gostaria muito de ver o applicationContext.xml, tá complicado de encontrar material na internet tratando do assunto.