Hoje vamos explorar um exemplo de acesso e autorização baseados em funções no Spring Security. No entanto, antes de ler esta postagem, por favor, dê uma olhada na minha postagem anterior sobre “Exemplo de Login e Logout com Spring 4 Security MVC” para obter algum conhecimento básico sobre o Spring 4 Security.
Spring Security Role
Nesta postagem, discutiremos como definir, usar e gerenciar funções de segurança do Spring, como “USER” e “ADMIN” em uma aplicação Spring Web. Assim como na minha postagem anterior, este exemplo também utiliza o Spring 4 MVC Security com Armazenamento em Memória e Recurso de Configuração Java do Spring para desenvolver a aplicação. Isso significa que não vamos usar o arquivo web.xml e também não escreveremos uma única linha de Configuração XML do Spring. Vamos usar a opção “In-Memory Store” para armazenar e gerenciar as credenciais do usuário. Estamos utilizando 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 Autorização de Acesso Baseado em Funções com Spring Security
- Crie um projeto “Simple Spring Web Maven” no Spring STS Suite com os seguintes detalhes.
Nome do Projeto: SpringMVCSecruityMavenRolesApp2. Use o mesmo arquivo pom.xml do meu post anterior com as seguintes alterações
<artifactId>SpringMVCSecruityMavenRolesApp</artifactId>
<build>
<finalName>SpringMVCSecruityMavenRolesApp</finalName>
</build>
</project>
- Use todos os arquivos Java e JSP do meu post anterior. Vamos discutir apenas o conteúdo atualizado ou recém-adicionado aqui.
- Atualize o arquivo LoginSecurityConfig.java para configurar funções de usuário como “USER” e “ADMIN”.
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("jduser").password("jdu@123").authorities("ROLE_USER")
.and()
.withUser("jdadmin").password("jda@123").authorities("ROLE_USER","ROLE_ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/homePage").access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
.antMatchers("/userPage").access("hasRole('ROLE_USER')")
.antMatchers("/adminPage").access("hasRole('ROLE_ADMIN')")
.and()
.formLogin().loginPage("/loginPage")
.defaultSuccessUrl("/homePage")
.failureUrl("/loginPage?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/loginPage?logout");
}
}
Explicação do Código
- No método configureGlobal(), foram adicionados dois usuários: Um usuário com a função “ROLE_USER” e outro usuário com as funções “ROLE_USER” e “ROLE_ADMIN”. Isso significa que esse segundo usuário atuará como um usuário administrador. Podemos configurar qualquer número de usuários e funções dessa forma.
- Podemos usar métodos authorities(ROLE) ou roles(ROLE) para configurar funções em nossa aplicação.
- Diferença entre os métodos authorities() e roles():
- authorities() precisa do nome completo da função como “ROLE_USER”
- roles() precisa do nome da função como “USER”. Ele adicionará automaticamente o valor “ROLE_” a esse nome de função “USER”.
- No método configure(), definimos diferentes URLs com as funções de acesso necessárias.
antMatchers("/homePage")
.access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
Este trecho de código configura que “/homePage” está disponível para as funções USER e ADMIN.
.antMatchers("/userPage").access("hasRole('ROLE_USER')")
.antMatchers("/adminPage").access("hasRole('ROLE_ADMIN')")
Este trecho de código configura que “/userPage” só é acessível pela função “USER” e “/adminPage” só é acessível pela função “ADMIN”. Se outras funções acessarem essas páginas, receberemos a mensagem de erro “403 Acesso Negado”.
- Atualize o arquivo de controle LoginController.java para definir novos caminhos de acesso URL, conforme mostrado abaixo.
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 = {"/userPage"}, method = RequestMethod.GET)
public ModelAndView userPage() {
ModelAndView model = new ModelAndView();
model.setViewName("userPage");
return model;
}
@RequestMapping(value = {"/adminPage"}, method = RequestMethod.GET)
public ModelAndView adminPage() {
ModelAndView model = new ModelAndView();
model.setViewName("adminPage");
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 Além do exemplo anterior, aqui foram adicionados mais dois novos URLs.
-
“/userPage” é utilizado pelo papel de USUÁRIO para acessar e realizar atividades normais de usuário.
-
“/adminPage” é utilizado pelo papel de ADMINISTRADOR para acessar e realizar atividades de administrador. O papel de ADMINISTRADOR também pode acessar a URL “/userPage”.
-
Atualizei o arquivo homePage.jsp para fornecer atividades específicas para os papéis de Usuário e Administrador.
homePage.jsp
<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<a href="${pageContext.request.contextPath}/userPage">JD User</a> | <a href="${pageContext.request.contextPath}/adminPage">JD Admin</a> | <a href="javascript:document.getElementById('logout').submit()">Logout</a>
<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>
Aqui, adicionamos três opções de menu ao quadro superior. “Logout” já foi discutido em meu post anterior. As duas novas ligações são:
- JD User: Acessível pelos papéis “USUÁRIO” e “ADMINISTRADOR”
- JD Admin: Acessível apenas pelos papéis “ADMINISTRADOR”
NOTA:- Em aplicações em tempo real, mostraremos apenas o link “JD User” para o papel “USUÁRIO” e ocultaremos o link “JD Admin”. Para testar se é acessível pelo papel “USUÁRIO” ou não, e também para ver a mensagem de erro exata, não ocultamos este link.20. Adicione um novo arquivo adminPage.jsp para atuar como uma página inicial para o papel “ADMINISTRADOR”.
adminPage.jsp
<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<h3>Welcome to JournalDEV Tutorials</h3>
<h3>Admin Page</h3>
<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>
- Adicione um novo arquivo userPage.jsp para atuar como uma página inicial para o papel de “USUÁRIO”.
userPage.jsp
<%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core"%>
<h3>Welcome to JournalDEV Tutorials</h3>
<h3>User Page</h3>
<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>
Concluímos agora o desenvolvimento de nossa aplicação. É hora de ver a estrutura final do nosso projeto e testar a aplicação.26. A estrutura final do projeto se parece com isso:
Teste da Aplicação de Exemplo de Funções do Spring Security
- Clique com o botão direito no projeto no ambiente de desenvolvimento Spring STS e selecione a opção “Run AS >> Run on Server”.
Isso acessará a página inicial padrão da aplicação, conforme mostrado abaixo:3. Clique no link “Login to JournalDEV”. Agora você está na página de login.
5. Faça o primeiro login com as credenciais da função “USER”:
Nome de usuário: jduser Senha: jdu@123Agora veremos a página inicial da aplicação com 3 opções de menu: “JD User”, “JD Admin” e “Logout”. Clique no link “JD User”. Como entramos na aplicação usando as credenciais da função “USER”, podemos acessar este link, conforme mostrado abaixo.
Use a seta de retorno no ambiente Spring STS e desta vez clique no link “JD Admin”.
Como entramos com as credenciais da função “USER”, não podemos acessar este link. É por isso que vimos a mensagem de erro: “403 Acesso negado”. 9. Agora, faça logout e faça login novamente com as credenciais da função “ADMIN”:
Nome de usuário: jdadmin Senha: jda@123 Desta vez, podemos acessar com sucesso o link “JD Admin”, conforme mostrado abaixo.Teste o link “Logout” para sair da aplicação.
Isso é tudo sobre o exemplo de papéis de segurança do Spring para fornecer acesso autorizado às páginas da aplicação web.