Como fazer para não acessar os jsp via URL?

Bom dia pessoal.
Minha dúvida é a seguinte: estou fazendo um sistema de login em java, que busca um usuario e senha no banco de dados e os direciona para determinadas páginas, dependendo do seu nível de acesso. Até aqui tudo bem.
Estou tendo problemas na questão de segurança do acesso das jsp’s. Qualquer pessoa pode digitar a URL das páginas jsp’s (inclusive paginas administrativas) e acessa-las. Pesquisei muito na internet sobre isso, e vi várias formas de fazer, inclusive usando filtros, usando o PhaseListener, usando o Realm. Mas, a forma mais simples que eu vi (pra mim), foi colocando as jsp’s dentro da pasta WEB-INF. Eu fiz isso e realmente funcionou. O problema, é que tem q mudar os caminhos dentro da jsp para acessar o banco e as outras jsp’s. Quando eu faço isso, a minha jsp mainpage fica em branco no navegador. Olha como estao os meus jsp’s e os xml’s.

olajsf.jsp=======================

[code]<%@page contentType=“text/html”%>
<%@page pageEncoding=“UTF-8”%>
<%@taglib prefix=“f” uri=“http://java.sun.com/jsf/core”%>
<%@taglib prefix=“h” uri=“http://java.sun.com/jsf/html”%>

Sistema de Login
        <h:form id="login_form">
            <h:panelGrid  columns="2" id="login_panel">
                <f:facet name="header">
                    <h:outputText value="Login" />
                </f:facet>
                <f:facet name="footer">
                    <h:commandButton value="Logar" action="#{LoginHandler.login}"/>
                </f:facet>
                
                                   
                <!--campo usuario-->
                                    
                <h:outputLabel for="usuario">
                    <h:outputText value="Usuario"/>
                </h:outputLabel>
                <h:inputText value="#{LoginHandler.LO.usuario}" id="usuario" />
                
                <!--campo senha-->
                
                <h:outputLabel for="password">
                    <h:outputText value="password"/>
                </h:outputLabel>                    
                <h:inputSecret value="#{LoginHandler.LO.password}" id="password" />
            </h:panelGrid>
        </h:form>       
    </body>
</f:view>
[/code]

mainpage.jsp===========

[code]<%@ taglib uri=“http://java.sun.com/jsf/core” prefix=“f”%>
<%@ taglib uri=“http://java.sun.com/jsf/html” prefix=“h”%>
<%@ taglib uri=“http://richfaces.org/a4j” prefix=“a4j” %>
<%@ taglib uri=“http://richfaces.org/rich” prefix=“rich” %>

sistema de contas a pagar !
<rich:tabPanel>
	<rich:tab label="Fornecedores">
<h:form id="Cadastro">
	<h:outputText value="#{msgs['fornecedor-nome']}" />
	<br />
	<h:inputText id="nome" required="true"
		value="#{fornecedorHandler.fornecedor.nome}"
		validator="#{fornecedorHandler.validaCase}">
		<f:validateLength minimum="5" />
	</h:inputText>
	<h:message for="nome" style="color: darkred" />
	<br />

	<h:outputText value="#{msgs['fornecedor-descricao']}" />
	<br />
	<h:inputTextarea id="descricao"
		value="#{fornecedorHandler.fornecedor.descricao}" />
	<h:message for="descricao" style="color: darkred" />
	<br />
	<h:commandButton value="Salvar" action="#{fornecedorHandler.salva}" />
</h:form>

<rich:spacer height="10"/>
<rich:separator height="1" lineType="dotted"/>
<rich:spacer height="10"/>

<jsp:include page="lista.jsp" />
</rich:tab>
<rich:tab label="Contas a Pagar">
	<jsp:include page="contas.jsp"/>
</rich:tab>
</rich:tabPanel>

</f:view>

[/code]

contas.jsp ===================

[code]<%@ taglib uri=“http://java.sun.com/jsf/core” prefix=“f”%>
<%@ taglib uri=“http://java.sun.com/jsf/html” prefix=“h”%>
<%@ taglib uri=“http://richfaces.org/a4j” prefix=“a4j” %>
<%@ taglib uri=“http://richfaces.org/rich” prefix=“rich” %>

Contas a pagar
<f:subview id="contas">
	<h:form>
		<h:panelGrid>
		<h:outputText value="Fornecedor"/>
		<h:selectOneMenu binding="#{contaPagarHandler.fornecedorSelecionado}">
			<f:selectItem itemValue="0" itemLabel="Selecione Fornecedor"/>
			<f:selectItems value="#{contaPagarHandler.fornecedoresParaComboBox}" />
		</h:selectOneMenu>
		
		<h:outputText value="Descrição"/>
		<h:inputText value="#{contaPagarHandler.contaPagar.descricao}"/>
		
		<h:outputText value="Data de pagamento"/>
		<rich:calendar value="#{contaPagarHandler.contaPagar.data.time}"/>
		
		<h:outputText value="Valor"/>
		<h:inputText value="#{contaPagarHandler.contaPagar.valor}"/>
		
		<h:selectBooleanCheckbox value="#{contaPagarHandler.contaPagar.pago}">
			<h:outputText value="Pago? "/></h:selectBooleanCheckbox>
		
		<h:messages/>
		
		<h:commandButton actionListener="#{contaPagarHandler.salva}" value="gravar"/>
		
		<rich:dataList value="#{contaPagarHandler.contas}" var="conta">
			<h:outputText value="#{conta.descricao}"/>
			<h:outputText value=" - "/>
			<h:outputText value="#{conta.fornecedor.nome}"/>
			</rich:dataList>
	</h:panelGrid>
	</h:form>
</f:subview>
[/code]

lista.jsp=====================

[code]<%@ taglib uri=“http://java.sun.com/jsf/core” prefix=“f”%>
<%@ taglib uri=“http://java.sun.com/jsf/html” prefix=“h”%>
<%@ taglib uri=“http://richfaces.org/a4j” prefix=“a4j” %>
<%@ taglib uri=“http://richfaces.org/rich” prefix=“rich” %>

lista
	<h:column>
		<f:facet name="header">
			<h:outputText value="Alterar"/>
		</f:facet>
		<h:commandLink actionListener="#{fornecedorHandler.escolheFornecedor}">
		<h:outputText value="(alterar)"/>
			<f:param id="editId" name="id" value="#{f.id}"/>
		</h:commandLink>
	</h:column>
	
	<%--Rodape com o paginador--%>
	<f:facet name="footer">
		<rich:datascroller/>
	</f:facet>
	
	</rich:dataTable>


</h:form>

</f:subview>

[/code]

web.xml=======================

[code]<?xml version="1.0" encoding="UTF-8"?>

projetojsf

index.html index.htm index.jsp default.html default.htm default.jsp olajsf.jsp org.richfaces.SKIN blueSky javax.faces.STATE_SAVING_METHOD server Ajax4jsf Filter ajax4jsf org.ajax4jsf.Filter ajax4jsf Faces Servlet REQUEST FORWARD INCLUDE
<filter>
	<filter-name>HibernateSessionFilter</filter-name>
	<filter-class>br.com.caelum.fj26.util.HibernateSessionFilter</filter-class>
</filter>

<filter-mapping>
	<filter-name>HibernateSessionFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>	
Faces Servlet javax.faces.webapp.FacesServlet 1 Faces Servlet /faces/* *.jsf [/code]

faces-config.xml===================

[code]<?xml version="1.0" encoding="UTF-8"?>



messages

pt
en

<managed-bean>
	<managed-bean-name>LoginHandler</managed-bean-name>
	<managed-bean-class>br.com.caelum.fj26.LoginHandler</managed-bean-class>
	<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

<managed-bean>
	<managed-bean-name>fornecedorHandler</managed-bean-name>
	<managed-bean-class>br.com.caelum.fj26.FornecedorHandler</managed-bean-class>
	<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
	<managed-bean-name>contaPagarHandler</managed-bean-name>
	<managed-bean-class>br.com.caelum.fj26.ContaPagarHandler</managed-bean-class>
	<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

<managed-bean>
	<managed-bean-name>usuarioHandler</managed-bean-name>
	<managed-bean-class>br.com.caelum.fj26.UsuarioHandler</managed-bean-class>
	<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

<navigation-rule>
	<from-view-id>/olajsf.jsp</from-view-id>
	<navigation-case>
		<from-outcome>ok</from-outcome>
		<to-view-id>/WEB-INF/jsp/mainpage.jsp</to-view-id>
	</navigation-case>
</navigation-rule>

<navigation-rule>
	<from-view-id>/olajsf.jsp</from-view-id>
	<navigation-case>
		<from-outcome>admin</from-outcome>
		<to-view-id>/admin.jsp</to-view-id>
	</navigation-case>
</navigation-rule>

<navigation-rule>
	<from-view-id>/olajsf.jsp</from-view-id>
	<navigation-case>
		<from-outcome>erro</from-outcome>
		<to-view-id>/olajsf.jsp</to-view-id>
	</navigation-case>
</navigation-rule>

<!-- <navigation-rule>
	<from-view-id>/*</from-view-id>
	<navigation-case>
		<from-outcome>loginPage</from-outcome>
		<to-view-id>/olajsf.jsp</to-view-id>
	</navigation-case>
</navigation-rule>
br.com.caelum.fj26.util.AuthorizationListener -->

[/code]

A pagina de login (olajsf.jsf) diretamente dentro da WebContent, já as paginas mainpage, contas e lista estão dentro de WebContent/WEB-INF/jsp.
A mainpage.jsp chama através de um rich:tab as paginas contas e lista. Se eu nao modificar os endereços, ela abre normal, mas quando eu salvo um cadastro ou clico na aba de contas, ela dá um erro que nao encontra a pagina. Se eu modificar na linha por exemplo:

[code]<jsp:include page=“contas.jsp”/>

<jsp:include page=“WebContent/WEB-INF/jsp/contas.jsp”/>[/code]

ele abre a página, só que toda em branco.

E ae pessoal, alguem tem alguma dica do que eu posso estar fazendo errado?? Sou iniciante no java, e pelo que eu vi, esse é o método mais simples pra implementar essa segurança.

Desde já agradeço a todos.

Olá…

Uma coisa que você pode fazer é utilizar sessão. Não diria que é uma forma arrojada de segurança mas ajuda a não se acessar uma determinada URL se não estiver com uma sessão aberta.

É uma coisa bem tosca mas vamos lá…
Primeiramente você cria qualquer variavel e coloca na sessão na classe que efetua o login na sua aplicação.

HttpSession session = request.getSession(true);

session.setAttribute( name , object )

Em todas as peginas, você coloca a notação validando se a sessão existe:

        if(session.getAttribute( name ) = null){
              ***redirect para a pagina de login****
        
}

Não validei o codigo acima, mas acho que dá para entender a situação…se não existir a sessão carregada no login, não será aberto as outras paginas e sim redirecionado a pagina de login…porque a notação que valida se existe uma sessão vai estar em todas as paginas…
Agora o ideal seria colocar que a sessão expire depois de um determinado tempo de inatividade…isso vc encontra por aí…

espero ter ajudado.

[quote=rockstorm]Olá…

Uma coisa que você pode fazer é utilizar sessão. Não diria que é uma forma arrojada de segurança mas ajuda a não se acessar uma determinada URL se não estiver com uma sessão aberta.

É uma coisa bem tosca mas vamos lá…
Primeiramente você cria qualquer variavel e coloca na sessão na classe que efetua o login na sua aplicação.

HttpSession session = request.getSession(true);

session.setAttribute( name , object )

Em todas as peginas, você coloca a notação validando se a sessão existe:

        if(session.getAttribute( name ) = null){
              ***redirect para a pagina de login****
        
}

Não validei o codigo acima, mas acho que dá para entender a situação…se não existir a sessão carregada no login, não será aberto as outras paginas e sim redirecionado a pagina de login…porque a notação que valida se existe uma sessão vai estar em todas as paginas…
Agora o ideal seria colocar que a sessão expire depois de um determinado tempo de inatividade…isso vc encontra por aí…

espero ter ajudado.
[/quote]

Olá rockstorm, td bem?
Agradeço pela sugestão que você deu e achei uma boa idéia. O problema é que eu tenho um conhecimento muito básico em java, e estou tendo dificuldades em algumas coisas na tua sugestão:

1: eu colei o teu código na minha classe responsável pelo login. Adicionei o import do HttpSession da classe “javax.servlet.http.HttpSession”, está correto?
2: o request da mesma linha não foi reconhecido. Eu tenho q criar uma variavel, ou algo parecido?
3: as variáveis name, object são as que eu devo usar? em que parte do meu projeto?

Desculpe pelas dúvidas, que podem parecer até idiotas, mas pra quem está começando, pode crer que atormentam.

Agradeço a colaboração.

Qual é essa classe que você faz login? O request é um HttpServletRequest, que é parâmetro de qualquer método de uma Servlet. O name seria como uma chave, um identificador do atributo para você pegá-lo depois. O object seria o usuário, ou o login do usuário.

A classe que eu faço a conexão com o bd é a classe LoginDAO. Olhe abaixo o código dela, que foi onde eu coloquei o código que vc me passou:

[code]
package br.com.caelum.fj26.dao;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpSession;

public class LoginDAO {

public LoginDAO() {
}

//metodo doFilter Implementado aqui
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws ServletException, IOException {
HttpSession session = request.getSession(true);
}

public boolean Login(String usuario, String password, String nivel) {
	boolean ok = false;
	// boolean admin = false;

	try {
		Class.forName("org.postgresql.Driver").newInstance();
		System.out.println("DRIVER CARREGADO");
	} catch (Exception e) {
		System.out.println("driver nao carregado");
	}

	try {
		String sql = "SELECT * from Usuario where usuario=? AND password=? AND nivel=?";

		// comentei para usar o conexao.class
		Connection c = DriverManager.getConnection(
				"jdbc:postgresql://localhost:5432/teste", "postgres",
				"postgres");
		PreparedStatement pstm = c.prepareStatement(sql);
		pstm.setString(1, usuario);
		pstm.setString(2, password);
		pstm.setString(3, nivel);
		ResultSet rs = pstm.executeQuery();
		System.out.println("CONEXAO ESTABELECIDA");
		if (rs.next()
				&& rs.getString("usuario") != null
				&& // necessario?
				rs.getString("usuario").equals(usuario)
				&& rs.getString("password").equals(password)
				&& rs.getString("nivel").equals(nivel)) {
			ok = true;
			System.out.println("Usuario carregado");

//implementado por último
session.setAttribute(“logado”, usuario);

		}
	} catch (SQLException ex) {
		ex.printStackTrace();
	}
	return ok;

}

}[/code]

Agora, a minha classe que tem a regra da conexão - LoginHandler:

[code]package br.com.caelum.fj26;

import java.util.List;

import org.hibernate.Session;

import br.com.caelum.fj26.dao.Dao;
import br.com.caelum.fj26.dao.LoginDAO;
import br.com.caelum.fj26.modelo.Login;
import br.com.caelum.fj26.modelo.Usuario;
import br.com.caelum.fj26.util.HibernateUtil;

public class LoginHandler {

private LoginDAO loginDAO = new LoginDAO();

/** Creates a new instance of ControleLogin */
public LoginHandler() {

}

private Login LO = new Login();

// 
public Login getLO() {
	return LO;
}

public void setLO(Login LO) {
	this.LO = LO;
}

public String login() {
	System.out.println("usuario= " + LO.getUsuario());
	System.out.println("password= " + LO.getPassword());

	boolean ok = loginDAO.Login(LO.getUsuario(), LO.getPassword(), "1");
	if (ok == true) {
		return "ok";

	}
	boolean admin = loginDAO.Login(LO.getUsuario(), LO.getPassword(), "2");
	if (admin == true) {
		return "admin";
	} else
		return "erro";
}

public List<Usuario> getUsuarios() {
	System.out.println("carregando usuarios ...");
	Session session = HibernateUtil.currentSession();
	Dao<Usuario> dao = new Dao<Usuario>(session, Usuario.class);
	return dao.list();
}

}[/code]

Eu sei que eu estou errando um erro besta, mas é assim que a gente aprende… hehehe
Cara, valeu a ajuda. Poucas pessoas se prestam a ajudar os iniciantes assim. Valeu.

Bom…vamos lá.

Na primeira classe que carrego do meu sistema, no meu caso seria quando vou efetuar o login, e coloco o usuário na sessão:

HttpSession session = request.getSession(true);
session.setAttribute("userSession",login.getUsername()); // o login.getUsername() seria o usuário que digitei na pagina mas vc pode coloca qualquer coisa..string

em casa pagina JSP depois da pagina de login, eu coloco:

<%
String user = null;
	if((String)session.getAttribute("userSession") != null){

			user = (String)session.getAttribute("userSession");
	}else{
	
		    response.sendRedirect("paginadelogin.jsp");
	}
%>

com isso, tenho o usuário logado em todas as paginas…caso se tente abrir uma destas paginas sem estar logado, a condição if((String)session.getAttribute(“userSession”) != null) vai cair em um redirect para onde voce quizer porque não vai existir usuário logado.

1: eu colei o teu código na minha classe responsável pelo login. Adicionei o import do HttpSession da classe “javax.servlet.http.HttpSession”, está correto?
R: Sim, esta correto

2: o request da mesma linha não foi reconhecido. Eu tenho q criar uma variavel, ou algo parecido?
R: o request seria nas paginas jsp

3: as variáveis name, object são as que eu devo usar? em que parte do meu projeto?
R: a variavel name que usei só foi um exemplo, voce pode colocar qualquer coisa, e tende deixar no inicio do codigo assim que criar global

Me diz uma coisa: a minha jsp tem aquelas abas dentro dela que chamam outras jsp’s. e em cada uma dessas jsp’s eu chamo uma session para acessar ao banco.

eu nao poderia chamar a session apenas uma vez (no caso, no login) e utitlizar nas outras jsp’s até o usuario expirar ou dar logoff?? eu acho que é isso que tá me dando trabalho.

Criei uma classe chamada ValidaAcessoFilter para validar a session para o login do usuario que ficou assim:

[code]package br.com.caelum.fj26.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

public class ValidaAcessoFilter implements Filter {

public void doFilter(ServletRequest req, ServletResponse resp,
		FilterChain chain) throws IOException, ServletException {
	HttpServletRequest request = (HttpServletRequest) req;
	HttpSession session = request.getSession();
	session.setAttribute("logado", request);
	System.out.println("FILTRO CARREGADO");
}

public void init(FilterConfig arg0) throws ServletException {
}

public void destroy() {
}

}[/code]

Só que eu uso tambem uma classe HibernateSessionFilter que fornece a session para as outras jsp’s que eu tenho que é assim:

[code]package br.com.caelum.fj26.util;

import java.io.IOException;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

public class HibernateSessionFilter implements Filter {

public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc)

		throws IOException, ServletException {



	HibernateUtil.openSession();

	try {

		HibernateUtil.currentSession().beginTransaction();

		fc.doFilter(req, res);

		HibernateUtil.currentSession().getTransaction().commit();

	} catch (Exception e) {

		throw new ServletException(e);

	} finally {

		HibernateUtil.closeCurrentSession();

	}

}



public void init(FilterConfig c) {

}



public void destroy() {

}

}
[/code]

A minha dúvida é aquela: eu tenho q usar as duas classes de filtro?? Se eu tiver que usar as duas classes, eu tenho que criar a session para cada jsp que o usuario chamar ou posso chama-la apenas uma vez (no caso no login do usuario) e usar essa mesma session até o usuario dar logout ou expirar? Alem isso, posso usar o mesmo método em duas classes de filtro diferentes??

Agradeço a todos pela colaboraçao.