Faculdade de Tecnologia SENAC Goiás
Projeto Integrador
Programação com Frameworks
Tutorial Financeiro WEB
Spring Security
Fernando Norberto Juliana Carvalho Thiago Junior Ester Xavier GTI V Matutino 2014Passo 1
Configurando o servidor Apache Tomcat 7.0
1) Crie uma nova pasta com o nome de Servidores na unidade C:\ de seu computador.2) Faça o Download do arquivo .Zip : http://tomcat.apache.org/download-70.cgi Baixe o arquivo zip (pgp, md5) , conforme a estrutura a seguir: Binary Distributions ● Core: ○ zip (pgp, md5) ○ tar.gz (pgp, md5) ○ 32bit Windows zip (pgp, md5) ← Para win 32. ○ 64bit Windows zip (pgp, md5) ← Para win 64. ○ 64bit Itanium Windows zip (pgp, md5) ○ 32bit/64bit Windows Service Installer (pgp, md5) 3) Salve o arquivo zip (pgp, md5) dentro da pasta Servidores. 4) Abrir a IDE Eclipse (Versão Kleper JEE) e definir o espaço de trabalho na janela Workspace Launcher. Sendo esse espaço de trabalho o diretório onde os projetos serão armazenados. 5) Para criar um novo servidor, clique no link: (No servers are avaliable) Caso a guia Servers não esteja visível, siga o caminho a seguir :
Clicando em “Other” , abrirá uma nova Janela , conforme o exemplo: Selecione a opção Servers, Para criar a seguinte Estrutura:
6) Clique no link descrito acima, abrirá a janela a seguir: 7) Dentro da Pasta “Apache”, selecione Tomcat v7.0 Server e clique em next. 8) Na próxima janela clique no Botão Browse e selecione o servidor tomcat, que se encontra dentro da pasta Servidores, exemplo abaixo:
9) Clique em Installed JRes... , abrirá uma nova janela, clique em “ADD”, clicando em add abrirá uma nova janela , conforme o exemplo: 10) Selecione a opção Standard VM e clique em next, abrirá a janela JRE Definition, conforme a seguir:
11) Em “JRE home” clique no botão“Directory” e selecione a pasta onde o JDK (Kit de desenvolvimento java) está instalado, após clicar observe as alterações seguintes, conforme na imagem: 12) Clique em “Finish”, e depois selecione o arquivo que foi configurado e clique em “ok”, conforme a seguir:
13) Selecione o arquivo que foi configurado e clique em ok. 14) Na próxima janela, selecione o “JDK” que foi configurado, conforme o exemplo: Nesse exemplo foi configurado o JDK 1.8 15) Após selecionar o JDK, clique em next, depois em finish. 16) Verifique se o servidor foi criado na guia Servers, conforme o exemplo a seguir: 17) Conforme a imagem acima, clique com o botão direito em cima do Servidor Tomcat, depois disso clique em “Start”, para rodar o servidor, se tudo der certo ele irá ficar da seguinte forma:
18) Pronto, seu servidor foi configurado corretamente.
Passo 2
Criando o Projeto
1) Crie um Projeto usando a ferramenta Eclipse, com o nome: FinanceiroWeb. 2) O projeto ficará com a seguinte estrutura:Classes e Interfaces
Páginas
Passo 3
Configurando e instalando o
Spring Security
Descrição
O Spring Security garante a autenticação e a autorização dos usuários, permitindo assim que somente quem realmente é cadastrado no sistema tenha acesso aos recursos restritos , com acesso somente ao conteúdo para o qual receba a permissão, no conteúdo restrito teremos 3 níveis de autorização: usuário normal, usuário administrador e usuário Vip.
O que é o Spring?
É um framework Java e de códigofonte aberto que visa facilitar o desenvolvimento JavaEE. A funcionalidade básica do Spring é a instanciação de classes, realizando a injeção de dependências com base em definições em um arquivo de configuração XML criado pelo desenvolvedor, resultando baixo acoplamento entre as classes.
O que o Spring faz por nós?
● Segurança de Pastas. Na pasta Admin foi criada a listagem de usuários, e apenas o usuário cadastrado com permissão de Administrador terá acesso a pasta. Os usuários cadastrados com permissão de apenas usuário, terão acesso apenas as pastas Publico, e Restrito. Concluindo então, ao separar adequadamente os recursos do sistema em pastas diferentes e ao configurar o Spring secutiry podemos garantir a segurança do acesso a determinadas pastas. ● Controle de Login Sempre que alguém tentar acessas alguma pasta do sistema que tenha a segurança garantida pelo Spring security, será apresentada a automaticamente a tela de login para a autenticação. ● Acesso a dados de usuários e permissõesPara que o Spring Security saiba quem são os usuários validos do sistema e suas permissões, poderemos informar quais são as SQLs que trazem essas informações do banco de dados. O Spring Security será configurado para utilizar a mesma conexão que o Hibernate utiliza.
Instalação e configuração do SPRING SECURITY
1) Faça o Download do spring : http://static.springsource.org/springsecurity/site/downloads.html , a versão mais nova disponível é a 3.0, clique no link download. 2) A estrutura do arquivo obtido é a seguinte: springsecurity3.0 +docs +dist 3) Dentro da pasta “+dist “ , você encontrará o arquivo “ springsecuritysamplescontacts<versão>.war ” . 4) Extraia o arquivo “ springsecuritysamplescontacts<versão>.war ” e renomeie para .zip ( springsecuritysamplescontacts<versão>.zip),. 5) Dentro dele obtenha os arquivos jars do diretório WEBINF/lib , Copie esses arquivos para o diretório WEBINF/lib do projeto FinanceiroWeb , no Eclipse. ● Adaptação da conexão do Hibernate para o Spring: Atualmente a configuração do banco de dados está declarada no arquivo hibernate.cfg.xml, mas agora precisaremos que o Spring também se conecte ao banco de dados. Para evitar que seja necessário ter 2 arquivos de configuração de banco de dados para o mesmo projeto, vamos tirar essa configuração de dentro do Hibernate e compartilhala entre o Hibernate e o Spring. Para configurarmos um Data Source de conexões no projeto, será necessário criar o arquivo context.xml e alterar os arquivos web.xml e hibernate.cfg.xml. O arquivo contexto.xml permite que configurações sobre o aplicativo, que estariam no arquivo CATALINA_HOME\conf\server.xml, possam ser declaradas no próprioaplicativo. Isso facilita a manutenção de tais configurações no ambiente de desenvolvimento. 6) O arquivo context.xml, deve ser criado em WebContent/METAINF , conforme o exemplo a seguir : <?xml version="1.0" encoding="UTF8"?> <!DOCTYPE xml> <Context reloadable="true"> <Resource name="jdbc/FinanceiroDB" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="postgres" ←Nome no banco. password="root" ←Senha do Banco driverClassName="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/BD"/> ←Caminho do banco </Contex 6.1) Alteração do Arquivo hibernate.cfg:
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEhibernate-configurationPUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factoryname=""> <!-- <property name="hibernate.connection.driver_class">org.postgresql.Driver</property> <property name="hibernate.connection.password">123456</property> <property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/bd_financeiro_pf</prop erty> <property name="hibernate.connection.username">postgres</property> -->
<propertyname="connection.datasource">java:comp/env/jdbc/FinanceiroDB</property> <propertyname="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property> <!-- -->
<propertyname="current_session_context_class">thread</property> <propertyname="hibernate.hbm2ddl.auto">update</property>
<!--Usando as configurações do C3PO para pool de conexão v --> <propertyname="c3po.min_size">5</property>
<propertyname="c3po.max_size">20</property> <propertyname="c3po.timeout">300</property>
<propertyname="c3po.max_statements">50</property> <propertyname="c3po.idle_test_period">3000</property> <!-- Configurações de debug -->
<propertyname="show_sql">true</property> <propertyname="format_sql">true</property>
<propertyname="generate_statistics">true</property> <propertyname="use_sql_comments">true</property> <!-- -->
<mappingclass="org.financeiro.model.usuario.Usuario"/> <mappingclass="org.financeiro.model.conta.Conta"/> <mappingclass="financeiro.categoria.Categoria"/> </session-factory> </hibernate-configuration> 7) O arquivo web.xml deve ser alterado , completo deverá ficar da seguinte forma : <?xml version="1.0" encoding="UTF8"?> <webapp xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/webapp_3_0.xsd" id="WebApp_ID" version="3.0"> <displayname>FinanceiroWeb</displayname> <welcomefilelist> <welcomefile>index.xhtml</welcomefile> </welcomefilelist> <servlet> <servletname>Faces Servlet</servletname> <servletclass>javax.faces.webapp.FacesServlet</servletclass> <loadonstartup>1</loadonstartup> </servlet> <servletmapping> <servletname>Faces Servlet</servletname> <urlpattern>*.xhtml</urlpattern> </servletmapping> <contextparam> <paramname>javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_ TIMEZONE</paramname> <paramvalue>true</paramvalue> </contextparam> <! Spring Security >
<contextparam> (1)← <paramname>contextConfigLocation</paramname> <paramvalue> /WEBINF/applicationContext.xml /WEBINF/applicationContextsecurity.xml </paramvalue> </contextparam> <contextparam> <paramname>com.sun.faces.expressionFactory</paramname> <paramvalue>com.sun.el.ExpressionFactoryImpl</paramvalue> </contextparam> <filter> (2)← <filtername>springSecurityFilterChain</filtername> <filterclass>org.springframework.web.filter.DelegatingFilterProxy</filterclass> </filter> <filtermapping> (3)← <filtername>springSecurityFilterChain</filtername> <urlpattern>/*</urlpattern> (4)← </filtermapping> <listener> <listenerclass>org.springframework.web.context.ContextLoaderListener</listenerclass> </listener>(5)← <filter> <filtername>conexaoFiter</filtername> <filterclass>org.financeiro.web.filter.ConnectionFactoryFilter</filterclass> </filter> <filtermapping> <filtername>conexaoFiter</filtername> <urlpattern>*.xhtml</urlpattern> </filtermapping> <resourceref> <description>DataSource Financeiro</description> <resrefname>jdbc/FinanceiroDB</resrefname> <restype>java.sql.DataSource</restype> <resauth>Container</resauth> </resourceref> <servlet> <servletname>Resource Servlet</servletname> <servletclass>org.primefaces.resource.ResourceServlet</servletclass> <loadonstartup>1</loadonstartup> </servlet>
<servletmapping> <servletname>Resource Servlet</servletname> <urlpattern>/primefaces_resource/*</urlpattern> </servletmapping> <contextparam> <paramname>com.sun.faces.allowTextChildren</paramname> <paramvalue>true</paramvalue> </contextparam> </webapp> ● A configuração em (1)← , com o nome contextConfigLocation informa quais são os arquivos de configurações disponíveis.
● As configurações em (2)← e (3)← , permitirão que o Spring Security intercepte todas as requisições realizadas, conforme explicado anteriormente. A configuração /* em <urlpattern> (4)← , é o que faz com que todas as requisições sejam avaliadas. Se configuração fosse /*.jsp, somente os arquivos JSP seriam avaliados. ● A configuração em (5)←, permitirá que o Spring Security carregue os arquivos de configuração no momento em que o aplicativo web estiver sendo colocado no ar, junto com o servidor. 8) Crie o arquivo applicationContext.xml dentro de WEBINF, conforme o exemplo a seguir: <?xml version="1.0" encoding="UTF8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/springbeans3.0.xsd"> <bean id="financeiroDataSource" (1)← class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName"> <value>java:comp/env/jdbc/FinanceiroDB</value> </property> </bean> </beans>
8.1) A configuração em (1)← , cria a referência financeiroDataSource do tipo JndiObjectFactoryBean, apontando para o DataSourceJDNI jdbc/FinanceiroDB. Essa referencia será utilizada dentro do próximo arquivo de configuração do Spring Security. 9) Dentro de WEBINF, crie o arquivo applicationContextsecurity.xml, da seguinte forma: <?xml version="1.0" encoding="UTF8"?> <b:beans xmlns="http://www.springframework.org/schema/security" xmlns:b="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/springbeans3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/springsecurity3.0.xsd"> <http> (1)← <intercepturl pattern="/admin/**" access="ROLE_ADMINISTRADOR" /> (2)← <intercepturl pattern="/restrito/**" access="ROLE_USUARIO" /> <formlogin loginpage="/publico/login.xhtml" (3)← alwaysusedefaulttarget="true" defaulttargeturl="/restrito/principal.xhtml" authenticationfailureurl="/publico/login.xhtml?login_error=1" /> <logout/> (4)← <rememberme />(5)← </http> <authenticationmanager> <authenticationprovider>(6)← <jdbcuserservice datasourceref="financeiroDataSource"(7)← authoritiesbyusernamequery="SELECT u.login, p.permissao FROM usuario u, usuario_permissao p WHERE u.id = p.usuario AND u.login = ?" usersbyusernamequery="SELECT login, senha, ativo FROM usuario WHERE login = ?" /> </authenticationprovider> </authenticationmanager> </b:beans>
● O elemento (1)← , é um agrupador das configurações referentes ao contexto web do sistema. ● A configuração de quais páginas ou diretórios que serão seguros é efetuada com o elemento (2)←, no qual o atributo pattern expressa o padrão textual da URL, e o atributo acess é uma linha separada por vírgula dos nomes de permissões que terão acesso ao recurso. ● O elemento (3)←, configura o funcionamento da página de Login do Spring Security. Nele é possível configurar os seguintes atributos: Loginpage Alwaysusedefalttarget defaulttargeturl authenticationfailureurl ● O elemento (4)←, será utilizado para habilitar o recurso de logout para o sistema. Com o logout habilitado, basta chamar a URL/j_spring_security_logout para que o usuário seja direcionado para a página externa do sistema , tendo sua sessão invalidada. ● O elemento (5)←, é muito interessante, pois permite que, com a simples inserção de uma caixa de verificação , o login automático seja habilitado. ● A configuração que estiver definida em (6)←, dirá ao Spring quais são os usuários válidos do sistema e suas permissões. ● O elemento (7)←, permite declarar as SQLs que fornecerão os dados que o Spring Security necessita, vindas do banco de dados.
Página Login
<!DOCTYPEhtmlPUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <htmlxmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"> <ui:compositiontemplate="/templates/interna.xhtml"> <ui:definename="corpo">
<br/> <br/> <br/>
<divalign="center"> <h1>Login</h1>
<h:panelGrouprendered="#{!empty param.login_error}"> (2)←,
<spanstyle="font-color:red">Erro ao efetuar o login.</span><br/> <br/>
Motivo: #{SPRING_SECURITY_LAST_EXCEPTION.message} </h:panelGroup>
<formid="login"method="post" (3)←, action="${request.contextPath}/j_spring_security_check">
<table>
<tr><td>Login</td>
<td><inputtype='text'name='j_username'(4)←,
required="true"/></td></tr>
<tr><td>Senha</td>
<td><inputtype='password'name='j_password' (5)←, required="true"/></td></tr>
<tr><tdalign="right"><inputtype="checkbox"
name="_spring_security_remember_me"onclick="if (!confirm('Tem CERTEZA?')) return false;"/></td>
<td>Entrar automaticamente</td></tr> <tr><td> </td>
<td><inputtype="submit"value="Entrar"/></td> </tr>
</table> <script>
document.getElementById("login").j_username.value = "#{SPRING_SECURITY_LAST_USERNAME}";(6)←, </script> </form> </div> <br/> <br/>
<divalign="center"> <h:form>
<h:commandLinkvalue="Registre-se"action="#{usuarioBean.actionNovo}"/> </h:form> </div> </h:body> </ui:define> </ui:composition> </html>
● O conteúdo do bloco (2)←, só será exibido caso tenha ocorrido algum erro em uma tentativa de login anterior.
● O formulário de login em sí só começa em (3)←, . A primeira coisa que perceber é que esse formulário não utiliza as tags <h:form> e sim <form> do HTML. ● Os campos do formulário tem nome padronizados pelo Spring Security (4)←. ● Habilitar o Login automático (5)←. ● O Login da última tentativa também está disponível em (6)←, que ultilizamos para sempre preencher o campo Login.
Página Principal do usuário
<!DOCTYPEhtmlPUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <htmlxmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:sec="http://www.springframework.org/security/facelets/tags">(1)←, <ui:compositiontemplate="/templates/interna.xhtml">
<ui:definename="corpo"> <h:body>
<h:form>
<divalign="right"> <a
onclick="document.location='#{request.contextPath}/j_spring_security_logout'" title="Sair">
<u><b>Logout</b></u>(2)←,
<h:graphicImagelibrary="imagens"name="logout16.png"
style="border:0"/> </a> </div> </h:form>
<divalign="center"> <divalign="left">
</div>
<divalign="left">
<h2>#{request.remoteUser}, OLÁ!</h2>(3)←, </div>
<hr/> <h:form>
<sec:ifAnyGrantedroles="ROLE_USUARIO_VIP"> <divalign="center">
<h3>Usuário VIP!</h3> </div>
</sec:ifAnyGranted> </h:form>
<h:form>
<sec:ifAnyGrantedroles="ROLE_ADMINISTRADOR">(4)←, <divalign="center">
<h2>Bem-vindo Administrador!</h2> </div><br/>
<u>Administração</u><br/>
<h:commandLinkaction="/admin/principal"title="Administrativo"> <h:graphicImagelibrary="imagens"
name="administrativo16.png"/> </h:commandLink> </sec:ifAnyGranted> </h:form> <br/> <h:form> <div>
<h:commandButtonvalue="Conta Bancária"action="conta"/> <h:selectOneMenuvalue="#{contextoBean.contaAtiva.conta}"
valueChangeListener="#{contextoBean.setContaAtiva}"
rendered="#{!empty contextoBen}"
onchange="submit()">
<f:selectItemsvalue="#{contaBean.lista}"
var ="conta"itemValue="#{conta.conta}"
itemLabel="#{conta.descricao}"/> </h:selectOneMenu> </div> </h:form> <br/> <br/> <h:form>
</h:form> </div> </h:body> </ui:define> </ui:composition> </html> ● (1)←, tags do Spring. ● (2)←, realizar logout. ● (3)←, retorna o login do usuário logado. ● (4)←, permite decidir para quais permissões seu conteúdo será exibido, ele faz uma verificação pra saber qual a permissão do usuário, nesse caso essa parte só aparece para o usuário com a permissão de administrador.
Permissões
Quando cadastrado no sistema, um usuário já recebe a permissão padrão que é de usuário. As demais permissões só o administrador pode dar. Também podemos dar permissão pelo banco de dados: Exemplo: INSERT INTO usuario_permissao(usuario,permissao) VALUES ('1','ROLE_ADMINISTRADOR'); No exemplo acima foi concedida a permissão de administrador para o usuário = 1. Exemplo:
publicvoid salvar(Usuario usuario) { Long id = usuario.getId();
if (id == null || id == 0){
usuario.getPermissao().add("ROLE_USUARIO");
usuarioDAO.salvar(usuario);
CategoriaRN categoriaRN = new CategoriaRN(); categoriaRN.salvaEstruturaPadrao(usuario); } else {
usuarioDAO.atualizar(usuario);
}
No exemplo acima o usuário é salvo com permissão usuário.
● O usuário administrador pode dar permissões de acordo com o exemplo: Figura 1.0
Exemplos
● Página de usuário com permissão padrão (somente usuário): OBS: Não tem acesso a administração Figura 1.1
Nesse exemplo o usuário não teve acesso ao link de administração porque é um usuário comum, a verificação é feita através do código:
<sec:ifAnyGrantedroles="ROLE_USUARIO"> <divalign="center">
<h2>Bem-vindo Administrador!</h2> </div><br/>
<h:commandLinkaction="/admin/principal"title="Administrativo"> <h:graphicImagelibrary="imagens"
name="administrativo16.png"/> </h:commandLink> </sec:ifAnyGranted>
●
Usuário com permissão de administradorOBS: Usuário com permissão de administrador Figura 1.2
● Página do usuário com permissão administrador (Listagem de usuários):
Figura 1.3
Nesse caso o usuário teve acesso a essa página de administração, porque como na página (figura 1.2) ele tem acesso ao ícone de administração , através de uma verificação que o SPRING fez através do código:
<sec:ifAnyGrantedroles="ROLE_ADMINISTRADOR"> <divalign="center">
<h2>Bem-vindo Administrador!</h2> </div><br/>
<u>Administração</u><br/>
<h:commandLinkaction="/admin/principal"title="Administrativo"> <h:graphicImagelibrary="imagens"
name="administrativo16.png"/> </h:commandLink> </sec:ifAnyGranted>
No exemplo acima o caminho para a administração <h:commandLink action="/admin/principal"title="Administrativo"> ,
Só aparecerá para o usuário com a permissão de administrador, devido a TAG seguinte:
<sec:ifAnyGrantedroles="ROLE_ADMINISTRADOR"> </sec:ifAnyGranted>
Então, tudo o que estiver dentro desse código será exibido apenas para o usuário com permissão de administrador.