JavaRush /Blogue Java /Random-PT /JAAS - Introdução à Tecnologia (Parte 2)
Viacheslav
Nível 3

JAAS - Introdução à Tecnologia (Parte 2)

Publicado no grupo Random-PT
Continuação da primeira parte do artigo sobre JAAS. Vamos descobrir se é possível usar apenas anotações para JAAS e quais problemas encontraremos. Aprenderemos nesta parte quais ferramentas da API Servlet nos permitem tornar o código mais universal. E vamos resumir o que lemos.
JAAS - Introdução à Tecnologia (Parte 2) - 1

Continuação

Na primeira parte da revisão da tecnologia JAAS (veja " JAAS - Introdução à Tecnologia (Parte 1) ") analisamos o principal caso de uso do JAAS e da API do Servlet. Vimos que o contêiner de servlet Tomcat gerenciava a segurança de nossa aplicação web usando a arquitetura JAAS. Tendo conhecimento do “método de autenticação” e do “Reino de Segurança”, o próprio contêiner Tomcat nos forneceu a implementação necessária do mecanismo de autenticação e ele próprio nos forneceu o CallbackHandler, apenas usamos tudo em nosso módulo de login. A única coisa importante a lembrar é que o navegador salva os dados de login e senha transmitidos via autenticação BASIC. Portanto, para cada nova verificação usando o Chrome, você pode pressionar Ctrl+Shift+N para abrir uma nova janela para trabalhar no modo de navegação anônima.
JAAS - Introdução à Tecnologia (Parte 2) - 2

Anotações

A configuração usando XML está fora de moda há muito tempo. Portanto, é importante dizer que a partir da API do Servlet versão 3.0, temos a oportunidade de definir as configurações do servlet usando anotações, sem usar o arquivo descritor de implantação web.xml. Vamos ver como o gerenciamento de segurança mudará se usarmos anotações. E é possível implementar as abordagens descritas acima usando anotações? A especificação da API do Servlet e sua seção “ Anotações e capacidade de conexão ” nos ajudarão novamente a entender as anotações . Esta seção diz que uma declaração de servlet web.xmlpode ser substituída por uma anotação @WebServlet. Assim, nosso servlet ficará assim:
@WebServlet(name="app", urlPatterns = "/secret")
public class App extends HttpServlet {
A seguir, vejamos o capítulo “ 13.3 Segurança Programática ”. Diz que também podemos declarar uma restrição de segurança através de anotações:
@WebServlet(name="app", urlPatterns = "/secret")
@ServletSecurity(httpMethodConstraints = {
        @HttpMethodConstraint(value = "GET", rolesAllowed = "admin")
})
public class App extends HttpServlet {
Agora web.xmlresta apenas um bloco no nosso - login-config. O problema é que não há como substituí-lo de maneira fácil e simples. Devido à estreita conexão entre as configurações de segurança do aplicativo Web e as configurações de segurança do servidor Web, não existe uma maneira simples e universal de fazer isso, mesmo de forma programática. Este é um dos problemas com autenticação usando JAAS e API Servlet. Falando em bloco login-config, vale entender que se trata de uma descrição declarativa de Mecanismos de Autenticação, ou seja, mecanismos de autenticação. Ainda não existe uma maneira simples e universal de substituí-lo, porque... o processamento web.xmlacontece profundamente nos contêineres do servlet. Por exemplo, no Tomcat você pode consultar a fonte ContextConfig.java . Portanto, mesmo para o contêiner de servlet Tomcat existem várias opções e são todas diferentes. Por exemplo, se usarmos o contêiner de servlet Embedded Tomcat (ou seja, criamos um servidor web a partir do código), você pode ler sobre essas opções aqui: “ Embedded Tomcat com autenticação básica via código ”. Além disso, um exemplo geral de criação do Embedde Tomcat pode ser visto no guia da plataforma Heroku PaaS: “ Criar um aplicativo Java Web usando o Embedded Tomcat ”. Se o Tomcat não for usado no modo incorporado, para o Tomcat você poderá usar uma abordagem comumente usada - ouvintes de eventos. No Tomcat, este é " O componente LifeCycle Listener ". Ao mesmo tempo, é importante entender que os contêineres de servlet (no nosso caso o Tomcat) podem ter seus próprios carregadores de classes e não será possível simplesmente pegar e usar suas classes. Para o Tomcat você precisa entender o " COMO FAZER do Class Loader ". Em outro contêiner de servlet chamado Undertow, isso pode ser feito usando " Extensões de Servlet ". Como você pode ver, alguns forneceram mecanismos mais flexíveis, enquanto outros não. Como você pode ver, não existe uma opção única. Eles são todos muito diferentes. É possível de alguma forma fazer algo universal apenas com a API do Servlet e o JAAS? Na Internet você encontra uma proposta de utilização do Filtro Servlet para realizar autenticação sem bloqueio login-config. Vamos finalmente considerar esta opção. Isso nos permitirá repetir como funciona o JAAS.
JAAS - Introdução à Tecnologia (Parte 2) - 3

Filtro de autenticação

Portanto, nosso objetivo é livrar-se web.xmlcompletamente do arquivo. Se nos livrarmos dele, infelizmente, não poderemos mais usar a Restrição de Segurança, porque seu processamento pode ocorrer muito antes da aplicação dos filtros do servlet. Esta é a taxa que você deve pagar pela “versatilidade” do uso de filtros. Aqueles. teremos que remover a anotação @ServletSecuritye todas as verificações que descrevemos anteriormente na restrição de segurança deverão ser realizadas programaticamente. Como você pode ver, esta opção também nos impõe muitas restrições desagradáveis. Primeiro de tudo, vamos remover a anotação @ServletSecuritydo recurso e o bloco login-configdo arquivo web.xml. Agora, nós mesmos teremos que implementar a autenticação Básica. Agora vamos adicionar nosso filtro:
@WebFilter("/*")
public class JaasFilter implements javax.servlet.Filter {
Até agora parece simples. Vamos escrever um método de inicialização:
@Override
public void init(FilterConfig filterConfig) throws ServletException {
	String jaas_conf = filterConfig.getServletContext().getRealPath("/WEB-INF/jaas.config");
	System.getProperties().setProperty("java.security.auth.login.config",jaas_conf);
}
Como você pode ver, agora somos forçados a usar ferramentas JAAS básicas para procurar o arquivo de configuração jaas. Isso tem uma grande desvantagem: se houver vários aplicativos, um aplicativo poderá quebrar a autenticação de outro. Como geralmente você pode configurar um arquivo Jaas Config é descrito em detalhes na documentação do JAAS: " Apêndice A: Configurações JAAS no arquivo de propriedades de segurança java.security ". A seguir, descreveremos o próprio método de filtragem. Vamos começar recebendo uma solicitação HTTP:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
	HttpServletRequest req = (HttpServletRequest) request;
	// Если в реквесте уже есть Principal - ничего не делаем
	if (req.getUserPrincipal() != null ) {
		chain.doFilter(request, response);
	}
Tudo é simples aqui. Se o Principal estiver disponível, a autenticação foi bem-sucedida. A seguir, você precisa descrever as ações do filtro quando o usuário não passou na autenticação, ou seja, ele ainda não foi reconhecido. Anteriormente descrevemos o método básico de autenticação, BASIC. Porque Como agora estamos escrevendo o filtro, teremos que descobrir como a autenticação BASIC realmente funciona. Você pode usar " documentos da web MDN: autorização HTTP ". E também " Como funciona a autenticação HTTP? " A partir da descrição de como funciona a autenticação Básica, fica claro que se o servidor deseja realizar a autenticação BASIC e o usuário não forneceu os dados, o servidor envia um cabeçalho especial "WWW-Authenticate" e o código de erro 401. Vamos criar um método interno para isso:
private void requestNewAuthInResponse(ServletResponse response) throws IOException {
	HttpServletResponse resp = (HttpServletResponse) response;
	String value = "Basic realm=\"JaasLogin\"";
	resp.setHeader("WWW-Authenticate", value);
	resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
Agora vamos usar este método e adicionar doFiltero seguinte bloco de código ao método:
// Получаем security Header. А если его нет - запрашиваем
String secHeader = req.getHeader("authorization");
if (secHeader == null) {
	requestNewAuthInResponse(response);
}
Agora vamos adicionar um branch for if, que será executado quando o cabeçalho já tiver sido transmitido:
// Проверяем аутентификацию
else {
	String authorization = secHeader.replace("Basic ", "");
	Base64.Decoder decoder = java.util.Base64.getDecoder();
	authorization = new String(decoder.decode(authorization));
	String[] loginData = authorization.split(":");
	try {
		if (loginData.length == 2) {
			req.login(loginData[0], loginData[1]);
			chain.doFilter(request, response);
		} else {
			requestNewAuthInResponse(response);
		}
	} catch (ServletException e) {
		requestNewAuthInResponse(response);
	}
}
Você pode adicionar autorização a este código, por exemplo: req.isUserInRole("admin") Então fizemos a autenticação com você usando um filtro. Por um lado, há muito código e processamento manual. Por outro lado, existe versatilidade e independência de servidor.
JAAS - Introdução à Tecnologia (Parte 2) - 4

Conclusão

Agora chegamos ao final desta revisão. Espero que agora fique um pouco mais claro o que é JAAS, o que é Sujeito e o que são Diretores. As palavras Security Realm e Login Config não levantarão mais dúvidas. Além disso, agora sabemos como usar o JAAS e a API do Servlet juntos. Além disso, aprendemos sobre gargalos onde as anotações na API do Servlet não nos salvarão. Claro, isso não é tudo. Por exemplo, a autenticação em Java pode não ser apenas BASIC. Você pode ver outros tipos na especificação da API do Servlet na seção " 13.6 Autenticação ". É difícil encontrar informações detalhadas sobre JAAS na Internet. Mas posso recomendar este material: Espero que as informações desta revisão sejam úteis e compreensíveis. #Viacheslav
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION