Spring Security 3 + facelets + JSF 2.0 problemas no login

11 respostas
J

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

11 Respostas

J

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?

J

jaboot bom dia

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

Obrigado

J

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

J

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

J

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

J

Problema resolvido.

Resolução postada acima.

Obrigado

L

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.

J

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.

L

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

A

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

A

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

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

Criado 28 de março de 2012
Ultima resposta 25 de abr. de 2013
Respostas 11
Participantes 5