Hoje vamos analisar um exemplo de acesso e autorização baseados em funções de segurança da primavera. No entanto, antes de ler este post, por favor, dê uma olhada no meu post anterior sobre “Exemplo de Login e Logout do Spring 4 Security MVC” para obter algum conhecimento básico sobre o Spring 4 Security.
Função de Segurança da Primavera
Neste post, discutiremos como definir, usar e gerenciar funções de segurança da primavera, como “USUÁRIO” e “ADMINISTRADOR” em uma aplicação web da primavera. Assim como no meu post anterior, este exemplo também está usando o Spring 4 MVC Security com o Armazenamento em Memória e o Recurso de Configuração Java da Primavera para desenvolver a aplicação. Isso significa que não vamos usar o arquivo web.xml e também não escreveremos nem uma única linha de Configuração XML da Primavera. Vamos usar a opção “Armazenamento em Memória” para armazenar e gerenciar as Credenciais do Usuário. Vamos usar 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 compilação Maven para desenvolver este exemplo.
Exemplo de Autorização de Acesso Baseado em Funções da Primavera Security
- Crie um projeto “Simple Spring Web Maven” no Spring STS Suite com os seguintes detalhes.
Nome do Projeto: SpringMVCSecurityMavenRolesApp2. Utilize 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. Discutiremos 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(), adicionamos 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 este segundo usuário atuará como um Usuário Administrador. Podemos configurar qualquer número de usuários e funções desta forma.
- Podemos usar os 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 este nome de função “USER”.
- No método configure(), definimos diferentes URLs com 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” é acessível apenas pela função “USER” e “/adminPage” é acessível apenas pela função “ADMIN”. Se outras funções acessarem essas páginas, receberemos a mensagem de erro “403 Access is Denied”.
- Atualize o arquivo de controle LoginController.java para definir novos caminhos de acesso URL conforme mostrado abaixo.
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 = {"/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 adicionamos mais dois novos URLs.
-
“/userPage” é usado pela função USUÁRIO para acessar e realizar atividades de usuário normal.
-
“/adminPage” é usado pela função ADMIN para acessar e realizar atividades de usuário administrador. A função ADMIN também pode acessar o URL “/userPage”.
-
Atualizado o arquivo homePage.jsp para fornecer atividades específicas para as funções 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 no topo. “Logout” já foi discutido em minha postagem anterior. Os dois novos links são:
- JD Usuário: Acessível tanto pelas funções “USUÁRIO” quanto “ADMIN”
- JD Administrador: Acessível apenas pela função “ADMIN”
NOTA:- Em aplicações em tempo real, mostraremos apenas o link “JD Usuário” para a função “USUÁRIO” e ocultaremos o link “JD Administrador”. Para testar se é acessível pela função “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 a função “ADMIN”. 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 servir como 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>
Nós concluímos o desenvolvimento de nossa aplicação agora. É 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 de Exemplo de Aplicativo de Funções de Segurança do Spring
- Clique com o botão direito no projeto no IDE Spring STS e selecione a opção “Executar como >> Executar no Servidor”. Isso acessará a página de boas-vindas do aplicativo padrão conforme mostrado abaixo:
3. Clique no link “Login no JournalDEV”. Agora você está na página de login.
5. Faça o login pela primeira vez com as credenciais do “USER”: Nome de usuário: jduser Senha: jdu@123
Agora veremos a página inicial do aplicativo com 3 opções de menu: “JD User”, “JD Admin” e “Logout”. Clique no link “JD User”. Como fizemos login no aplicativo usando as credenciais do “USER”, podemos acessar este link conforme mostrado abaixo.
Basta usar a seta para trás no IDE Spring STS e desta vez clicar no link “JD Admin”.
Como fizemos login com as credenciais do “USER”, não podemos acessar este link. Por isso vimos esta mensagem de erro: “403 Acesso negado”.9. Agora faça logout e faça login novamente com as credenciais do “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 do aplicativo.
Isso é tudo sobre o exemplo de papéis de segurança do Spring para fornecer acesso autorizado às páginas da aplicação web.