Como hospedar arquivos estáticos em um CDN com o Casdoor: S3, MinIO, Azure Blob e outros provedores de armazenamento
Para hospedar arquivos estáticos em um CDN, coloque-os no armazenamento de objetos (Amazon S3, MinIO, Azure Blob Storage, Google Cloud Storage, Alibaba Cloud OSS ou Tencent Cloud COS), faça o CDN buscar desse bucket como sua origem e distribua URLs no domínio do CDN. No Casdoor, isso é uma única configuração: crie um provedor de armazenamento para o bucket e coloque o endereço do CDN no campo Domain. O Casdoor envia avatares e outros arquivos por meio da API do provedor e salva URLs que começam com esse domínio. O frontend do próprio Casdoor também pode vir de um CDN, por meio de frontendCdnUrl e staticBaseUrl em app.conf.
Provedores de armazenamento em resumo
Um provedor de armazenamento decide onde o Casdoor grava os arquivos enviados: avatares de usuários, imagens de documentos de identidade, páginas de termos de uso e qualquer coisa enviada na página Resources. Você adiciona o provedor a uma aplicação, e os envios feitos nessa aplicação vão para ele. A visão geral dos provedores de armazenamento lista todos os tipos. Esta tabela cobre aqueles sobre os quais as pessoas geralmente perguntam:
| Armazenamento | Tipo de provedor do Casdoor | O Casdoor usa a API S3? | Auto-hospedável | Como a URL pública é definida |
|---|---|---|---|---|
| Sistema de arquivos local | Local File System | Não, arquivos simples em disco | Sim, é o servidor do Casdoor | Servido pelo Casdoor sob /files/. Domain é somente leitura |
| Amazon S3 | AWS S3 | Sim | Não | Domain: a URL do bucket ou um domínio CloudFront. Endpoint (Intranet): um endpoint VPC |
| MinIO | MinIO | Sim, com requisições path-style | Sim | Domain: a URL do MinIO seguida pelo nome do bucket, ou um domínio de CDN |
| Alibaba Cloud OSS | Aliyun OSS | Não, o SDK OSS | Não | Domain: um domínio de CDN. Se estiver vazio, torna-se bucket.endpoint. Endpoint (Intranet): o endpoint interno |
| Tencent Cloud COS | Tencent Cloud COS | Não, a API COS | Não | Domain: um domínio de CDN |
| Azure Blob Storage | Azure Blob | Não, a API Blob | Não | Domain: um domínio personalizado ou Front Door. O Casdoor adiciona o nome do contêiner ao caminho |
| Google Cloud Storage | Google Cloud Storage | Não, o cliente Go do Google | Não | Domain: se estiver vazio, torna-se https://storage.googleapis.com. O Casdoor adiciona o nome do bucket ao caminho |
| Synology NAS | Synology | Não, a API DSM File Station | Sim | Sem campo Domain. A URL é baseada no Endpoint |
O Casdoor também suporta Qiniu Cloud Kodo, CUCloud OSS e Casdoor, que armazena arquivos em outra instância do Casdoor. Os guias por provedor para Amazon S3, MinIO, Azure Blob, Google Cloud Storage, Alibaba Cloud OSS, Tencent Cloud COS, Synology NAS e o sistema de arquivos local mostram qual valor vai em qual campo.
Endpoint vs. Domain
Esses dois campos têm funções diferentes, e a maioria dos problemas de CDN vem de confundi-los.
- Endpoint é o endereço que o Casdoor usa para falar com a API de armazenamento: upload, exclusão, listagem. O CDN não está envolvido.
- Endpoint (Intranet) substitui Endpoint quando
isCloudIntranet = trueestá definido emapp.conf. Isso mantém o tráfego de upload na rede interna do provedor quando o Casdoor executa na mesma nuvem. O campo aparece para AWS S3, Aliyun OSS, Azure Blob e CUCloud OSS. - Domain é a base da URL que o Casdoor salva e que os navegadores solicitam. Se você tiver um CDN, seu domínio vai aqui.
- Path prefix é colocado antes de cada chave de objeto. Com um prefixo
casdoor, um avatar termina sobcasdoor/avatar/....
O Casdoor constrói a URL do arquivo a partir do esquema e host do Domain, depois o caminho do Domain, depois o path prefix, depois o caminho do arquivo. Um Domain sem esquema recebe https://. A parte do caminho do Domain também se torna parte da chave do objeto, então https://cdn.example.com/casdoor/ armazena arquivos sob casdoor/ no bucket. Para Azure Blob e Google Cloud Storage, o Casdoor adiciona o nome do contêiner ou bucket como o primeiro segmento de caminho após o host. Seu CDN precisa servir esse caminho.
Se Domain estiver vazio, o Casdoor preenche-o a partir do endpoint do provedor na primeira vez que usa o provedor e o salva. Às vezes, o resultado funciona, como com OSS e GCS. Às vezes não: para um endpoint S3 sem o nome do bucket, ou para MinIO, onde requisições estilo-path colocam o nome do bucket no caminho, a URL gerada perde o bucket. Defina Domain você mesmo, faça upload de um avatar de teste e abra a URL que o Casdoor retorna antes que qualquer outra pessoa use.
O provedor que o Casdoor usa para avatars copiados de logins sociais vem de defaultStorageProvider em app.conf. É o nome de um provedor pertencente ao admin (veja a referência de configuração):
defaultStorageProvider = provider_storage_s3
isCloudIntranet = false
Buckets públicos, buckets privados e URLs assinadas
O Casdoor salva uma URL plana e permanente no campo avatar do usuário e no registro de recurso. Ele não cria URLs assinadas ou expiráveis para esses arquivos. Portanto, o que quer que esteja em Domain deve responder a um GET anônimo. Há duas maneiras de fazer isso.
Torne os objetos públicos. Com AWS S3 e MinIO, o Casdoor faz upload de cada objeto com a ACL canned public-read. Com Aliyun OSS, a biblioteca cliente faz o mesmo por padrão. No S3, isso conflita com os padrões para novos buckets: de acordo com a AWS, novos buckets usam a configuração Bucket owner enforced, que desabilita ACLs, e um upload que define uma ACL como public-read falha com AccessControlListNotSupported. É por isso que o guia Amazon S3 pede que você habilite ACLs e desative Block all public access. No OSS, uma ACL de objeto tem precedência sobre a ACL do bucket, então um objeto public-read pode ser lido mesmo em um bucket privado. O MinIO não usa a ACL para leituras anônimas. Ele usa uma política de bucket:
mc anonymous set download myminio/casdoor
Azure precisa permitir acesso anônimo na conta de armazenamento e o contêiner definido no nível de acesso Blob. Google Cloud Storage precisa da função Storage Object Viewer (roles/storage.objectViewer) concedida a allUsers no bucket.
Mantenha o bucket privado e deixe apenas o CDN lê-lo. O CDN assina suas requisições à origem, e os espectadores passam pelo CDN sem assinatura. Cada fornecedor tem sua própria versão:
- CloudFront tem controle de acesso à origem (OAC). A AWS exige Bucket owner enforced para OAC, ou Bucket owner preferred se você precisar de ACLs.
- Alibaba Cloud CDN pode buscar de um bucket OSS privado após você autorizá-lo.
- Tencent Cloud CDN tem autenticação de pull de origem para buckets COS privados.
- Azure Front Door Premium pode alcançar uma conta de armazenamento via Private Link.
- O guia do Cloud CDN do Google também cobre acesso a buckets privados, onde a função Storage Object Viewer é atribuída a uma conta de serviço em vez de
allUsers.
Isso oculta a URL própria do bucket, mas os arquivos ainda são públicos através do CDN. Com os tipos AWS S3 e Aliyun OSS, os objetos também permanecem legíveis em suas URLs de bucket, devido à ACL public-read que o Casdoor define.
Se os avatares não devem ser públicos de forma alguma, um CDN na frente do armazenamento de objetos é a ferramenta errada. Mantenha esses arquivos em um tipo de armazenamento que você controla e limite quem pode acessar esse host.
Cabeçalhos de cache e a armadilha do avatar
No S3 e MinIO, o Casdoor define Content-Type a partir da extensão do arquivo quando faz upload. Ele não define Cache-Control em nenhum provedor. Isso significa que o TTL padrão do CDN se aplica. No CloudFront, objetos sem Cache-Control são armazenados em cache pelo TTL padrão, que é de 24 horas quando você não usa uma política de cache. Para controlar isso por objeto, adicione metadados Cache-Control no bucket. Para todo um caminho, use uma regra de cache no CDN.
Avatars need a short TTL. When a user changes their picture, Casdoor writes the new file to the same key, avatar/<organization>/<username>.<extension>, and saves the same URL. A long TTL means people see the old picture until it expires or until you purge or invalidate that path. Other uploads get a numbered suffix (-1, -2, ...) when the name is already taken, so a new upload gets a new URL and can be cached for a long time.
Um layout que funciona:
| Caminho | Cache sugerido |
|---|---|
avatar/* | TTL curto (minutos), ou purge ao mudar |
resource/* e outros uploads | TTL longo |
Assets frontend com hash (assets/*) | TTL muito longo. O nome do arquivo muda a cada build |
O próprio frontend do Casdoor em um CDN
Separadamente dos uploads de usuários, há três maneiras de mover os arquivos estáticos próprios do Casdoor para fora do servidor Casdoor.
frontendCdnUrl. Use isto se você instalar o frontend do pacote npm casdoor-web. Aponte-o para um CDN npm, por exemplo:
frontendCdnUrl = "https://cdn.jsdelivr.net/npm/{name}@{version}"
O Casdoor lê o nome e a versão do pacote do package.json na pasta de build. Ele reescreve os links de script e folha de estilo em index.html para esse CDN e mantém os caminhos locais como fallback. Se um arquivo falhar ao carregar, o navegador o carrega do Casdoor, e um cookie mantém esse navegador nos arquivos locais pelo resto da sessão. Um frontend que você compila você mesmo não tem tal package.json, então a configuração não tem efeito nele.
O script de implantação. Para um frontend que você compila a partir do código-fonte, Hospedar os arquivos do frontend em um CDN explica deployment/deploy_test.go. Ele faz upload de web/build/assets/ por meio de um dos seus provedores de armazenamento e aponta o index.html para o Domain do provedor, que deve terminar com /. O Vite gera hashes nesses nomes de arquivo, portanto eles são adequados para o TTL longo na tabela acima.
staticBaseUrl. Isso define a origem das imagens padrão, como logotipos, ícones de provedores e o avatar padrão. O valor padrão é https://cdn.casbin.org, que serve o repositório casbin/static. Em uma rede sem acesso à internet, hospede uma cópia desse repositório você mesmo e aponte o staticBaseUrl para ela, conforme descrito em Hospedar arquivos estáticos em uma intranet.
Escolhendo uma opção
- Um servidor, base de usuários pequena:
Local File System. Monte o diretóriofilesem um volume se o Casdoor estiver sendo executado em um contêiner. O Casdoor enviaX-Content-Type-Options: nosniffe umaContent-Security-Policyde sandboxing com esses arquivos, para que um arquivo HTML ou SVG enviado não possa executar scripts no seu domínio do Casdoor. - Auto-hospedado e compatível com S3:
MinIO. É também o tipo sugerido pela documentação para outras lojas compatíveis com S3. - Já está em uma nuvem: use o armazenamento de objetos e o CDN dessa nuvem, defina Endpoint (Intranet) onde o Casdoor está sendo executado na mesma nuvem e defina o Domain para o CDN.
Referências
- Provedores de armazenamento do Casdoor e o código-fonte:
object/storage.go,storage/,routers/frontend_cdn.go - AWS: Controlando a propriedade de objetos e desabilitando ACLs, Restringir o acesso a uma origem Amazon S3, Gerenciar quanto tempo o conteúdo permanece no cache
- MinIO:
mc anonymous set - Microsoft: Configurar acesso de leitura anônimo para contêineres e blobs, Integrar uma conta de Armazenamento do Azure com o Azure Front Door
- Google Cloud: Tornar dados públicos, Configurar o Cloud CDN com um bucket de backend
- Alibaba Cloud: Object ACL, Busca de origem em buckets OSS privados
- Tencent Cloud: Configurando Aceleração de CDN para COS