{"id":15196788,"url":"https://github.com/lsmcodes/spring-security","last_synced_at":"2026-03-06T11:04:04.270Z","repository":{"id":248910007,"uuid":"829681593","full_name":"lsmcodes/spring-security","owner":"lsmcodes","description":"Resolução do exercício proposto durante o curso \"Adicionando Segurança a uma API REST com Spring Security\" - DIO","archived":false,"fork":false,"pushed_at":"2024-07-21T14:50:12.000Z","size":41,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-02T09:17:01.406Z","etag":null,"topics":["jwt","santander-bootcamp-2024","spring-boot","spring-framework","spring-security"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lsmcodes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-16T22:46:20.000Z","updated_at":"2024-07-21T14:56:58.000Z","dependencies_parsed_at":"2024-09-18T22:01:53.333Z","dependency_job_id":null,"html_url":"https://github.com/lsmcodes/spring-security","commit_stats":null,"previous_names":["lsmcodes/spring-security"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/lsmcodes/spring-security","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lsmcodes%2Fspring-security","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lsmcodes%2Fspring-security/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lsmcodes%2Fspring-security/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lsmcodes%2Fspring-security/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lsmcodes","download_url":"https://codeload.github.com/lsmcodes/spring-security/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lsmcodes%2Fspring-security/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30173373,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T07:56:45.623Z","status":"ssl_error","status_checked_at":"2026-03-06T07:55:55.621Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["jwt","santander-bootcamp-2024","spring-boot","spring-framework","spring-security"],"created_at":"2024-09-28T00:03:24.980Z","updated_at":"2026-03-06T11:03:59.253Z","avatar_url":"https://github.com/lsmcodes.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DIO - Trilha Spring Framework\n\n\u003cdiv style=\"display:inline-block\"\u003e\n        \u003cpicture\u003e\n                \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://img.shields.io/badge/Java-black?style=for-the-badge\u0026logo=OpenJDK\u0026logoColor=white\"\u003e\n                \u003cimg src=\"https://img.shields.io/badge/Java-white?style=for-the-badge\u0026logo=OpenJDK\u0026logoColor=black\" /\u003e\n        \u003c/picture\u003e\n        \u003cpicture\u003e\n                \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://img.shields.io/badge/Maven-black?style=for-the-badge\u0026logo=ApacheMaven\u0026logoColor=white\"\u003e\n                \u003cimg src=\"https://img.shields.io/badge/Maven-white?style=for-the-badge\u0026logo=ApacheMaven\u0026logoColor=black\" /\u003e\n        \u003c/picture\u003e\n        \u003cpicture\u003e\n                \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://img.shields.io/badge/Spring_Boot-black?style=for-the-badge\u0026logo=SpringBoot\u0026logoColor=white\"\u003e\n                \u003cimg src=\"https://img.shields.io/badge/Spring_Boot-white?style=for-the-badge\u0026logo=SpringBoot\u0026logoColor=black\" /\u003e\n        \u003c/picture\u003e\n\t\u003cpicture\u003e\n                \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://img.shields.io/badge/Spring Security-black?style=for-the-badge\u0026logo=SpringSecurity\u0026logoColor=white\"\u003e\n                \u003cimg src=\"https://img.shields.io/badge/Spring Security-white?style=for-the-badge\u0026logo=SpringSecurity\u0026logoColor=black\" /\u003e\n        \u003c/picture\u003e\n\t\u003cpicture\u003e\n                \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://img.shields.io/badge/JWT-black?style=for-the-badge\u0026logo=JsonWebTokens\u0026logoColor=white\"\u003e\n                \u003cimg src=\"https://img.shields.io/badge/JWT-white?style=for-the-badge\u0026logo=JsonWebTokens\u0026logoColor=black\" /\u003e\n        \u003c/picture\u003e\n\u003c/div\u003e\n\n## Autor dos Exercícios e Repositório Original\n\n* [Gleyson Sampaio](https://github.com/glysns)\n* [Spring Security e JWT](https://github.com/digitalinnovationone/dio-springboot/tree/main/dio-spring-security-jwt)\n\n## Exercício\n\nEste repositório contém um exercício que coloca em prática os seguintes temas:\n\n* Spring Security\n* Spring Data Jpa\n* JWT\n\n## Spring Security\n\n`Spring Security` é um framework altamente customizável que provê `autenticação e autorização`, sendo o framework de segurança padrão para aplicações baseadas em Spring.\n\n## Configurar Spring Security\n\nPara utilizar o Spring Security em uma aplicação Spring Web, basta adicionar o starter a seguir ao projeto.\n\n### Maven\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n    \u003cartifactId\u003espring-boot-starter-security\u003c/artifactId\u003e\n    \u003cversion\u003e3.3.1\u003c/version\u003e\n\u003c/dependency\u003e\n\n```\n\n### Gradle\n\n```groovy\nimplementation group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '3.3.1'\n\n```\n\n## Terminologia\n\nAlguns dos termos que devem ser compreendidos no contexto do Spring Security são:\n\n* `Autenticação`: é a forma pela qual a identidade de alguém que deseja acessar algum recurso é verificada;\n* `Autorização`: é determinar quais usuários tem acesso permitido a um determinado recurso;\n* `Principal`: é o objeto que identifica o usuário no contexto da autenticação. É frequentemente uma instância de UserDetails, uma interface cujas implementações armazenam informações de usuários e são gerenciadas por um UserDetailsService;\n* `GrantedAuthority`: é cada uma das permissões dadas a um usuário, muitas vezes representadas por papéis (roles) como ROLE_ADMIN ou ROLE_USER, para definir que um usuário é um administrador ou um usuário simples, respectivamente.\n\n## Autenticação Simples\n\nA `autenticação simples` é feita por meio de usuário e senha. O Spring Security oferece alguns mecanismos para a leitura dessas credenciais, sendo o padrão, o mecanismo de `formulário`. O formulário solicita as credenciais e pode ser acessado em localhost:8080/login após a adição do starter do Spring Security e com a aplicação em execução.\n\nAs credenciais padrões são user e a senha aleatória que é gerada e exibida no terminal a cada inicialização da aplicação dessa forma:\n\n```\nUsing generated security password: 25b3e4bb-cdbb-415d-8f17-0d059bbe5cc2\n```\n\n### Application Properties\n\nAs credenciais podem ser alteradas por meio do arquivo `application.properties`, como demonstrado abaixo.\n\n```properties\nspring.security.user.name=admin\nspring.security.user.password=1234\n```\n\n### Memória\n\nTambém é possível armazenar credenciais na `memória`, criando instâncias de UserDetails manualmente. Essa alternativa permite a criação de vários perfis de acesso. A seguir, é possível observar a criação de dois perfis de acesso.\n\n```java\n@Configuration\n@EnableWebSecurity\npublic class SecurityConfiguration {\n\n        @Bean\n        public UserDetailsService userDetailsService() {\n                // Perfil de acesso user\n                UserDetails user = User.withUsername(\"user\").password(\"{noop}user1234\").roles(\"USER\").build();\n\n                // Perfil de acesso admin\n                UserDetails admin = User.withUsername(\"admin\").password(\"{noop}admin1234\").roles(\"USER\", \"ADMIN\").build();\n\n                return new InMemoryUserDetailsManager(user, admin);\n        }\n\n}\n```\n\n### Banco de Dados\n\nA melhor alternativa para o armazenamento de credenciais é evidentemente o armazenamento em `banco de dados`. Para isso, é preciso configurar um banco de dados e utilizar o Spring Data Jpa para a criação de um repositório para armazenar os usuários que siga a seguinte estrutura:\n\n```java\npublic interface UserRepository extends JpaRepository\u003cUser, Long\u003e {\n\n        // Método que busca usuário pelo nome de usuário\n        public User findByUsername(String username);\n\n}\n```\n\nTambém é preciso definir como a criação de instâncias de UserDetails são criadas (aqui elas serão criadas automaticamente, ao contrário do armazenamento em memória), por meio da definição do método `loadUserByUsername`. Observe o exemplo a seguir que demonstra a busca do usuário no repositório, a definição de suas autoridades e por fim, a criação do perfil de acesso.\n\n```java\n@Service\npublic class SecurityService implements UserDetailsService {\n\n        @Autowired\n        private UserRepository repository;\n\n        @Override\n        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {\n                User foundUser = this.repository.findByUsername(username);\n\n                // Definição das autoridades do usuário\n                Set\u003cGrantedAuthority\u003e authorities = new HashSet\u003c\u003e();\n                foundUser.getRoles().forEach(role -\u003e authorities.add(new SimpleGrantedAuthority(\"ROLE_\" + role)));\n\n                // Criação do perfil de acesso\n                UserDetails user = new org.springframework.security.core.userdetails.User(\n                                foundUser.getUsername(),\n                                foundUser.getPassword(),\n                                authorities);\n\n                return user;\n        }\n\n}\n```\n\n## Autorização\n\nAssim como a autenticação, a autorização no Spring Security pode ser realizada de variadas formas, as mais comuns são por meio de segurança de método e de requisições HTTP.\n\n### Segurança de Método\n\nPor padrão, a segurança de método não é habilitada. Portanto, para utilizá-la, é necessário adicionar a anotação `@EnableMethodSecurity` em uma classe de configuração. Essa anotação permite o uso de outras anotações a nível de método, como `@PreAuthorize` que avalia uma expressão para decidir se o método anotado pode ser invocado ou não. Por exemplo, no trecho de código a seguir, é verificado se o usuário que está invocando o método, a partir da URL /admins possui a role ROLE_ADMIN. E se o usuário tiver essa role, o método é executado.\n\n```java\n// Define o método e a URI, que são GET e /admins, respectivamente\n@GetMapping(\"/admins\")\n@PreAuthorize(\"hasRole('ROLE_ADMIN')\")\npublic String admins() {\n        return \"Authorized admin\";\n}\n```\n\n### Autorizar Requisições HTTP\n\nO Spring Security permite também configurar a segurança a nível de requisições utilizado a interface `SecurityFilterChain`. Um bean dessa interface deve ser criado para a definição de uma cadeia de filtros da classe `HttpSecurity`, que configuram a segurança das requisições HTTP. Por exemplo, a configuração abaixo permite que a URI /admins receba apenas requisições GET de usuários que possuem a role ADMIN. Caso os usuários não tenham essa role, as requisições serão negadas.\n\n```java\n@Bean\npublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {\n        return http.authorizeHttpRequests(authorize -\u003e authorize\n                        .requestMatchers(HttpMethod.GET, \"/admins\").hasRole(\"ADMIN\")\n\n                        // As demais requisições devem ser apenas autenticadas, sem restrições relacionadas a roles\n                        .anyRequest().authenticated())\n                      \n                        // Define a utilização do formulário de login padrão\n                        .formLogin(Customizer.withDefaults())\n                        .build();\n}\n```\n\n## JWT (JSON Web Tokens)\n\n`JWT` é um padrão para transmissão de informações de forma segura entre partes na forma de um objeto JSON. A integridade dessas informações pode ser verificada por meio de uma assinatura digital. O cenário mais comum onde JWTs são utilizados é na autorização. Após a autenticação do usuário, um token JWT é retornado e todas as requisições subsequentes deverão o incluir no cabeçalho `Authorization` com o prefixo `Bearer`. Isso permite que o usuário acesse rotas, serviços, e recursos que são permitidos pelo token.\n\nJWTs são constituídos de três partes:\n\n* `Header`: consiste normalmente em duas partes: o tipo do token e o algoritmo de assinatura que está sendo utilizado;\n* `Payload`: parte do JWT que contém as reivindicações, ou seja, declarações sobre uma entidade (um usuário, por exemplo) e dados adicionais;\n* `Signature`: é a junção da header e do payload encriptados com base64 e uma chave secreta, assinados com o algoritmo de assinatura especificado no header.\n\n\u003cp align=\"center\"\u003e\n        \u003cimg src=\"assets/images/jwt.png\"\u003e\n\u003c/p\u003e\n\nO resultado são três strings codificadas em base64 separadas por pontos:\n\n```\neyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.\neyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.\nSflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c\n```\n\n## Referências\n\n* Spring Security - https://spring.io/projects/spring-security\n* Authentication - https://docs.spring.io/spring-security/reference/features/authentication/index.html\n* Authorization - https://docs.spring.io/spring-security/reference/features/authorization/index.html\n* Authentication Interface - https://docs.spring.io/spring-security/reference/servlet/authentication/architecture.html#servlet-authentication-authentication\n* Hello Spring Security - https://docs.spring.io/spring-security/reference/servlet/getting-started.html\n* Method Security - https://docs.spring.io/spring-security/reference/servlet/authorization/method-security.html\n* Authorize HttpServletRequests - https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html\n* Introduction to JSON Web Tokens - https://jwt.io/introduction\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flsmcodes%2Fspring-security","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flsmcodes%2Fspring-security","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flsmcodes%2Fspring-security/lists"}