Hoje vamos aprender sobre o exemplo de login do Spring Security. Antes de ler este post, por favor, passe pelo meu post anterior em “Introdução à Segurança do Spring 4” para obter algumas noções básicas.
Exemplo de Login e Logout do Spring Security
Neste post, vamos desenvolver uma Aplicação Web de Segurança do Spring 4 MVC para fornecer recursos de login e logout usando a opção In-Memory. Este exemplo utiliza a Configuração Java do Spring com Anotações do Spring, o que significa que não estamos usando web.xml e Configuração XML do Spring (Estilo Antigo). Se você não está familiarizado com o Módulo de Segurança do Spring 3.x, por favor, passe pelos seguintes posts primeiro para experimentar a Receita de Segurança do Spring.
- Exemplo de Segurança do Spring MVC usando autenticação em memória, UserDetailsService e JDBC
- Segurança do Spring em uma Aplicação Web Servlet usando autenticação DAO, JDBC, In-Memory
O Módulo de Segurança do Spring 4 suporta as seguintes opções para armazenar e gerenciar Credenciais de Usuário:
- Armazenamento em Memória
- Bancos de Dados Relacionais (RDBMS)
- Armazenamento de Dados NoSQL
- LDAP
Vamos usar a opção “In-Memory Store” neste exemplo. Vamos discutir outras opções em meus próximos posts. Vamos utilizar o Spring 4.0.2.RELEASE, Spring STS 3.7 Suite IDE, Spring TC Server 3.1 com Java 1.8 e a ferramenta de construção Maven para desenvolver este exemplo.
Exemplo de Login do Spring Security
Vamos desenvolver uma lógica de Login e Logout usando os recursos de Segurança do Spring 4. O principal objetivo desta aplicação é desenvolver uma aplicação sem usar “web.xml” e sem escrever uma única linha de configuração de Feijões XML do Spring. Isso significa que vamos usar o recurso Spring Java Config com Anotações Spring. Vamos desenvolver esta aplicação com as seguintes características:
- Página de Boas-Vindas
- Página de Login
- Página Inicial
- Recurso de Logout
Por favor, siga as etapas a seguir para desenvolver e explorar este exemplo simples de login do Spring 4 Security.
- Crie um projeto “Simple Spring Web Maven” no Spring STS Suite com os seguintes detalhes
Project Name : SpringMVCSecruityMavenApp
- Atualize o pom.xml com o seguinte conteúdo
<?xml version="1.0" encoding="UTF-8"?>
<project
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="https://maven.apache.org/POM/4.0.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev</groupId>
<artifactId>SpringMVCSecruityMavenApp</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<properties>
<java.version>1.8</java.version>
<spring.version>4.0.2.RELEASE</spring.version>
<spring.security.version>4.0.2.RELEASE</spring.security.version>
<servlet.api.version>3.1.0</servlet.api.version>
<jsp.api.version>2.2</jsp.api.version>
<jstl.version>1.2</jstl.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.api.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp.api.version}</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
</dependencies>
<build>
<finalName>SpringMVCSecruityMavenApp</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
NOTA:- Se você não estiver ciente da flag “<failOnMissingWebXml>”, leia no final deste post para obter uma boa compreensão do uso deste elemento. – Primeiro, desenvolva o controlador de login usando a anotação @Controller do Spring.
LoginController.java
package com.journaldev.spring.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class LoginController {
@RequestMapping(value = { "/"}, method = RequestMethod.GET)
public ModelAndView welcomePage() {
ModelAndView model = new ModelAndView();
model.setViewName("welcomePage");
return model;
}
@RequestMapping(value = { "/homePage"}, method = RequestMethod.GET)
public ModelAndView homePage() {
ModelAndView model = new ModelAndView();
model.setViewName("homePage");
return model;
}
@RequestMapping(value = "/loginPage", method = RequestMethod.GET)
public ModelAndView loginPage(@RequestParam(value = "error",required = false) String error,
@RequestParam(value = "logout", required = false) String logout) {
ModelAndView model = new ModelAndView();
if (error != null) {
model.addObject("error", "Invalid Credentials provided.");
}
if (logout != null) {
model.addObject("message", "Logged out from JournalDEV successfully.");
}
model.setViewName("loginPage");
return model;
}
}
Explicação do Código:- Definimos três métodos no “LoginController” para lidar com três tipos diferentes de Solicitações do Cliente
- welcomePage() lidará com todas as solicitações de cliente que estão usando o URI “/”.
- homePage() lidará com todas as solicitações de cliente que estão usando o URI “/homePage”.
- loginPage() lidará com todas as solicitações de cliente que estão usando o URI “/loginPage”.
- Na loginPage(), cuidamos do tratamento de mensagens de erro e logout.
- Em seguida, desenvolva uma classe “LoginSecurityConfig” para fornecer Recursos de Segurança de Login e Logout usando a API de Segurança Spring 4.
LoginSecurityConfig.java
package com.journaldev.spring.secuity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder authenticationMgr) throws Exception {
authenticationMgr.inMemoryAuthentication()
.withUser("journaldev")
.password("jd@123")
.authorities("ROLE_USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/homePage").access("hasRole('ROLE_USER')")
.and()
.formLogin().loginPage("/loginPage")
.defaultSuccessUrl("/homePage")
.failureUrl("/loginPage?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/loginPage?logout");
}
}
Explicação do Código:- Definimos dois métodos em “LoginSecurityConfig” para armazenar e gerenciar Credenciais de Usuário e cuidar dos recursos de Segurança de Login e Logout.
- @EnableWebSecurity A anotação é usada para habilitar a segurança web em qualquer aplicativo web.
- A anotação @EnableWebMVCSecurity é usada para habilitar a segurança na web em aplicativos da web baseados em Spring MVC.
NOTA:- @EnableWebSecurity = @EnableWebMVCSecurity + Recursos extras. É por isso que a anotação @EnableWebMVCSecurity está obsoleta no Framework Spring 4.x. A classe “LoginSecurityConfig” ou qualquer classe designada para configurar a segurança do Spring deve estender a classe “WebSecurityConfigurerAdapter” ou implementar a interface relacionada. - O método configureGlobal() é usado para armazenar e gerenciar credenciais de usuário.
- No método configureGlobal(), podemos usar o método authorities() para definir os papéis de nossa aplicação, como “ROLE_USER”. Também podemos usar o método roles() para o mesmo propósito.
- Diferença entre os métodos authorities() e roles():
- O método authorities() precisa de um nome de papel completo como “ROLE_USER” roles() precisa de um nome de papel como “USER”. Ele adicionará automaticamente o valor “ROLE_” a este nome de papel “USER”. NOTA:- Vamos desenvolver outro exemplo para demonstrar papéis como “USER”, “ADMIN” em meus próximos posts.
- Método importante para cuidar da segurança de login e logout é configure(HttpSecurity http)
- O trecho de código a seguir é usado para evitar o acesso não autorizado à “/homePage”. Se você tentar acessar esta página diretamente, será redirecionado automaticamente para a página “/loginPage”.
.antMatchers("/homePage").access("hasRole('ROLE_USER')")
Se removermos a chamada do método access(“hasRole(‘ROLE_USER’)”), então podemos acessar esta página sem fazer login em nossa aplicação. 13. Configuramos as funcionalidades de login e logout usando os métodos formLogin() e logout().
- Ative a Configuração do Spring MVC
LoginApplicationConfig.java
package com.journaldev.spring.secuity.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
@EnableWebMvc
@Configuration
@ComponentScan({ "com.journaldev.spring.*" })
@Import(value = { LoginSecurityConfig.class })
public class LoginApplicationConfig {
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
Explicação do Código:- Usamos a classe “LoginApplicationConfig” para definir os Visualizadores do Spring MVC a fim de evitar escrever o arquivo “web.xml”.
- @EnableWebMvc A anotação é usada para habilitar as funcionalidades de Aplicação Spring Web MVC no Framework Spring
- @Import A anotação é usada para importar a classe de Configuração do Spring Security para esta classe.
- @ComponentScan A anotação é usada para fazer a varredura de componentes no pacote especificado. É igual a “context:component-scan” na Configuração XML do Spring.
- Inicialize a Segurança do Spring
package com.journaldev.spring.secuity.config.core;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
“SpringSecurityInitializer” é usada para registrar o DelegatingFilterProxy
para usar o springSecurityFilterChain. Isso evita escrever a configuração de Filtros no arquivo web.xml. – Inicialize a Aplicação Spring MVC
A classe “SpringMVCWebAppInitializer” é usada para inicializar o “DispatcherServlet” sem o arquivo web.xml em uma configuração baseada em anotações. SpringMVCWebAppInitializer.java
package com.journaldev.spring.secuity.config.core;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import com.journaldev.spring.secuity.config.LoginApplicationConfig;
public class SpringMVCWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { LoginApplicationConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
OBSERVAÇÃO:-
- Quando acessamos nossa aplicação, por padrão, o método getServletMappings() do SpringMVCWebAppInitializer permitirá acessar a URL raiz: “/”. Podemos substituir para encaminhar para uma URL diferente.
- A equipe Spring ou Pivotal está trabalhando nesta questão para evitar tanto código Java, introduzindo uma anotação. Por favor, verifique isso em https://jira.spring.io/browse/SPR-10359.
- Desenvolva o arquivo welcomePage.jsp
<h3>Welcome to JournalDEV Tutorials</h3>
<a href="${pageContext.request.contextPath}/loginPage">Login to Journal</a>
- Desenvolva o arquivo loginPage.jsp
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<html>
<body onload='document.loginForm.username.focus();'>
<h3>JournalDEV Tutorials</h3>
<c:if test="${not empty error}"><div>${error}</div></c:if>
<c:if test="${not empty message}"><div>${message}</div></c:if>
<form name='login' action="<c:url value='/loginPage' />" method='POST'>
<table>
<tr>
<td>UserName:</td>
<td><input type='text' name='username' value=''></td>
</tr>
<tr>
<td>Password:</td>
<td><input type='password' name='password' /></td>
</tr>
<tr>
<td colspan='2'><input name="submit" type="submit" value="submit" /></td>
</tr>
</table>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
</body>
</html>
- Desenvolva o arquivo homepage.jsp
<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<h3>Welcome to JournalDEV Tutorials</h3>
<ul>
<li>Java 8 tutorial</li>
<li>Spring tutorial</li>
<li>Gradle tutorial</li>
<li>BigData tutorial</li>
</ul>
<c:url value="/logout" var="logoutUrl" />
<form id="logout" action="${logoutUrl}" method="post" >
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
<c:if test="${pageContext.request.userPrincipal.name != null}">
<a href="javascript:document.getElementById('logout').submit()">Logout</a>
</c:if>
Executar Exemplo de Login e Logout com Spring Security MVC
Para executar esta Aplicação Web Spring, precisamos de qualquer Contêiner Web que suporte o Spring 4 e Ambientes Java 8 com Servlet 3.1.0.
- Implantar e Executar no Spring TC Server na Suíte Spring STS
- Ele acessa automaticamente a URL da página de boas-vindas de nossa aplicação, conforme mostrado abaixo.
– clique no link “Login to JournalDEV” para acessar a página de login.
– Agora, forneça detalhes de login incorretos e clique no botão “Login”.
Aqui podemos observar a mensagem de erro: “Credenciais inválidas fornecidas.”- Agora, forneça os detalhes de login corretos configurados na classe “LoginSecurityConfig”.
Após o login bem-sucedido em nossa aplicação, podemos ver a página inicial com o link “Logout”.- clique no link “Logout” para sair da aplicação.
Aqui podemos observar que saímos com sucesso de nossa aplicação e fomos redirecionados para a página de login novamente. Podemos observar alguma mensagem de logout bem-sucedido nesta página de login.
NOTA:- Se observarmos este exemplo, não estamos a utilizar corretamente o ficheiro web.xml. Como se trata de uma Aplicação Web, o Maven procura o ficheiro web.xml e gera alguns erros se não o encontrar na aplicação. Para evitar problemas relacionados com o Maven, precisamos de configurar o sinalizador “<failOnMissingWebXml>” no ficheiro pom.xml. É isso tudo sobre o Exemplo Simples do Módulo de Segurança Spring 4. Vamos desenvolver mais exemplos úteis em tempo real nos meus próximos posts, como Gerenciamento de Funções, Funcionalidade de Lembrar-me, Segurança de WebSocket e muito mais. Por favor, deixe-me um comentário se gostou do meu post ou se tiver quaisquer problemas/sugestões.
Source:
https://www.digitalocean.com/community/tutorials/spring-4-security-mvc-login-logout-example