Exemplo de Autorização de Acesso Baseada em Funções do Spring Security

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

  1. 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>
  1. Use todos os arquivos Java e JSP do meu post anterior. Vamos discutir apenas o conteúdo atualizado ou recém-adicionado aqui.
  2. 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

  1. 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.
  2. Podemos usar métodos authorities(ROLE) ou roles(ROLE) para configurar funções em nossa aplicação.
  3. 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”.
  1. 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”.

  1. 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.

  1. “/userPage” é utilizado pelo papel de USUÁRIO para acessar e realizar atividades normais de usuário.

  2. “/adminPage” é utilizado pelo papel de ADMINISTRADOR para acessar e realizar atividades de administrador. O papel de ADMINISTRADOR também pode acessar a URL “/userPage”.

  3. 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:

  1. JD User: Acessível pelos papéis “USUÁRIO” e “ADMINISTRADOR”
  2. 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>
  1. 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

  1. 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@123 Agora 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.

Source:
https://www.digitalocean.com/community/tutorials/spring-security-role-based-access-authorization-example