Arquitetura de Governança de Permissões: Vue3, Spring Security, JWT, RBAC e Rotas Dinâmicas

Fundamentos da Governança em Plataformas de IA

A implementação de um sistema de gestão puramente baseado em operações CRUD é insuficiente para aplicações de IA de nível empresarial. Uma plataforma de governança robusta deve atuar como a base centralizada que suporta a autenticação, autorização e auditoria para módulos avançados, como gerenciamento de modelos, recuperação de informações (RAG) e integração de ferramentas (MCP). Isso exige o suporte a múltiplas identidades, controle de acesso multidimensional (páginas, botões e escopo de dados) e rastreabilidade rigorosa para conformidade.

Arquitetura de Backend: Spring Security e JWT

O núcleo de autenticação no backend é construído sobre Spring Boot e Spring Security, utilizando JSON Web Tokens (JWT) para manter a stateless session. O fluxo padrão envolve a emissão de um token Bearer após a validação de credenciais, o qual é subsequentemente utilizado para acessar a árvore de menus e validar permissões de recursos.

Abaixo está a configuração do filtro de segurança, reestruturada para desabilitar CSRF (adequado para APIs stateless) e integrar um filtro JWT personalizado entes do filtro de autenticação padrão:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

    private final JwtTokenFilter customJwtFilter;

    public WebSecurityConfig(JwtTokenFilter customJwtFilter) {
        this.customJwtFilter = customJwtFilter;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf(csrf -> csrf.disable())
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/v1/auth/login", "/api/v1/auth/refresh").permitAll()
                .requestMatchers("/api/v1/menus/tree").authenticated()
                .anyRequest().authenticated()
            )
            .addFilterBefore(customJwtFilter, UsernamePasswordAuthenticationFilter.class);
        
        return http.build();
    }
}

Para ambientes de produção, recomenda-se implementar mecanismos de renovação de token, listas negras para revogação forçada e isolamento de multitenancy através de filtros de contexto.

Frontend: Injeção Dinâmica de Rotas com Vue3

No frontend, a experiência do usuário é adaptada dinamicamente com base nas permissões. Após o login, o cliente solicita a árvore de menus autorizados e a converte em objetos de rota do Vue Router. Essa abordagem garante que usuários não autorizados nem mesmo carreguem os componentes de frontend restritos.

A estrutura de dados do menu e a lógica de conversão de rotas podem ser implementadas da seguinte forma:

import { RouteRecordRaw } from 'vue-router';

export interface MenuNode {
  nodeId: string;
  parentRef: string | null;
  routePath: string;
  viewComponent: string;
  accessTags: string[];
  isHidden: boolean;
}

// Carregamento.lazy de componentes de visualização
const viewModules = import.meta.glob('../views/**/*.vue');

export function generateDynamicRoutes(menuList: MenuNode[]): RouteRecordRaw[] {
  return menuList
    .filter(node => !node.isHidden)
    .map(node => ({
      path: node.routePath,
      name: node.nodeId,
      component: viewModules[`../views/${node.viewComponent}.vue`],
      meta: { 
        requiredPermissions: node.accessTags,
        title: node.nodeId 
      }
    }));
}

As rotas geradas são então injetadas no layout principal utilizando router.addRoute(), garantindo que a barra lateral e o conteúdo principal reflitam estritamente os privilégios do usuário.

Controle Granular e RBAC no Nível de Componente

O modelo RBAC (Role-Based Access Control) mapeia usuários para funções e funções para identificadores de permissão atômicos (ex: model:deploy, knowledgebase:delete). Para controlar a visibildiade de botões e ações específicas na interface, uma diretiva customizada do Vue é a solução mais elegante.

import { DirectiveBinding, ObjectDirective } from 'vue';
import { useAuthStore } from '@/stores/auth';

export const vAuth: ObjectDirective<HTMLElement, string> = {
  mounted(el: HTMLElement, binding: DirectiveBinding<string>) {
    const authStore = useAuthStore();
    const requiredAction = binding.value;
    
    if (!authStore.grantedPermissions.includes(requiredAction)) {
      el.parentNode?.removeChild(el);
    }
  }
};

// Uso no template:
// <button v-auth="'user:delete'">Excluir Usuário</button>

Essa diretiva remove fisicamente o elemento do DOM se a permissão não for encontrada no store do Pinia, prevenindo interações não autorizadas e limpando a interface.

Trilha de Auditoria e Internacionalização

A auditoria de operações sensíveis (como alterações de funções, exclusão de menus ou ajustes de permissões de modelos de IA) é crucial. A implementação via Aspect-Oriented Programming (AOP) no back end permite interceptar métodos anotados, registrando o contexto da requisição, o identificador do usuário e o resultado da operação de forma assíncrona para não degradar a performance da API.

Paralelamente, a internacionalização (i18n) deve ser tratada como um fluxo de trabalho contínuo. Em vez de codificar textos diretamente nos componentes, todas as strings de interface, incluindo mensagens de validação e erros de API, devem ser externalizadas para arquivos de recursos (ex: pt-BR.json, en-US.json), utilizando chaves semânticas como auth.password.min_length.

Estratégia de Banco de Dados e Inicialização

O esquema do banco de dados deve suportar relações muitos-para-muitos entre usuários, funções e permissões, além de hierarquias departamentais. As tabelas principais incluem sys_user, sys_role, sys_menu e sys_audit_log. É fundamental inicializar o banco de dados com um usuário administrador padrão, cujas credenciais devem ser obrigatoriamente alteradas no primeiro acesso. A senha deve ser armazenada utilizando algoritmos de hash robustos, como BCrypt, e a política de segurança deve exigir complexidade mínima e bloqueio após tentativas falhas.

Tags: vue3 SpringSecurity jwt rbac TypeScript

Publicado em 6-5 05:49 por Thomas