Первая часть учебник была включена базовую защиту по нашим Api. В этой второй части мы будем добавлять правила авторизации с помощью фао от содержащихся в токеном JWT. Эм примейру лугар, вамос альтерар носсо приложение.yaml e mudar a propriedade e o конечная точка делает использование ключа. Теперь это будет так:
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:8080/auth/realms/security-api/protocol/openid-connect/certs
Конечная точка Lembrando que nesse безопасность-api é o ном до носсо царство криадо без ключа.
Vamos para crear una classe que vai ser responsavel parex trairas власти делают токен JWT criado palo с ключом.
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import org.springframework.core.convert.converter.Converter; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter; import org.springframework.stereotype.Component; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; /** * Classe responsavel por converter o token gerado pelo Keycloak * de maneira a atribuir os authorities do jeito que o spring security * utiliza. */ @Component @RequiredArgsConstructor public class KeycloakJwtAuthenticationConverter implements Converter{ private final JwtGrantedAuthoritiesConverter defaultGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); private final ObjectMapper objectMapper; @Override public AbstractAuthenticationToken convert(Jwt jwt) { Collection authorities = Stream .concat(defaultGrantedAuthoritiesConverter.convert(jwt).stream() , extractAuthorities(jwt).stream()) .collect(Collectors.toSet()); return new JwtAuthenticationToken(jwt, authorities); } /** * orquestra a extração dos authorities * @param jwt * @return Collection contendo as roles e scopes do jwt */ private Collection extractAuthorities(Jwt jwt) { Set rolesWithPrefix = new HashSet<>(); rolesWithPrefix.addAll(getRealmRoles(jwt)); rolesWithPrefix.addAll(getResourceRoles(jwt)); return AuthorityUtils.createAuthorityList(rolesWithPrefix.toArray(new String[0])); } /** * Busca as roles de acesso ao realm * @param jwt * @return uma colection contendo as roles */ private Set getRealmRoles(Jwt jwt) { Set rolesWithPrefix = new HashSet<>(); JsonNode json = objectMapper.convertValue(jwt.getClaim("realm_access"), JsonNode.class); json.elements().forEachRemaining( e -> e.elements().forEachRemaining(r -> rolesWithPrefix.add(createRole(r.asText())))); return rolesWithPrefix; } /** * Busca as roles de acesso a determinado resource * @param jwt * @return uma colection contendo as roles */ private Set getResourceRoles(Jwt jwt) { Set rolesWithPrefix = new HashSet<>(); Map map = objectMapper.convertValue(jwt.getClaim("resource_access"), new TypeReference
Добавил, чтобы каждая role префикс ROLE_ и роли конкретного resource префикса включает в себя также имя resource. Теперь давайте создадим класс для конфигурации spring security.
import lombok.RequiredArgsConstructor; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 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; @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) @RequiredArgsConstructor public class ResourceServerConfig extends WebSecurityConfigurerAdapter { private final KeycloakJwtAuthenticationConverter keycloakJwtAuthenticationConverter; @Override public void configure(final HttpSecurity http) throws Exception { http .authorizeRequests(authz -> authz.antMatchers("/security/**").authenticated()) .oauth2ResourceServer() .jwt().jwtAuthenticationConverter(keycloakJwtAuthenticationConverter); } }
Здесь, кроме того, обеспечить безопасность, включено также @PreAuthorize и @PostAuthorize . Эти книжки получают выражения, написанные на SpEL (Spring Expression Language), и работает проверка на маркер, если клиент запрос имеет разрешения на доступ тот метод или получить доступ к тому, что произошло после выполнения метода, таких как названия аннотации предлагают. Вы можете узнать больше о том, expression-based access control в документации spring этом ссылки В конфигурации spring security, я сообщил, что только endpoint-ы запускаются /security должны быть проверены и setei класс, который мы создали выше, как преобразовать токен JWT.
Чтоб проверить, мы будем создавать конечные точки, необходимые:
import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(value = "/security") public class SecurityResource { /** * endpoint sem nenhuma validação de role */ @GetMapping public ResponseEntityisAuthenticated() { return ResponseEntity.ok().build(); } /** * endpoint onde o usuario tem que ter a role user */ @GetMapping(value = "/has-role") @PreAuthorize("hasAnyAuthority('ROLE_USER')") public ResponseEntity isUser() { return ResponseEntity.ok().build(); } /** * endpoint onde o usuario tem que ter a role admin */ @GetMapping(value = "/is-admin") @PreAuthorize("hasAnyAuthority('ROLE_ADMIN')") public ResponseEntity isAdmin() { return ResponseEntity.ok().build(); } }
В нашем проекте это все готово. Любой конечной точки, который начинается с security требуется токена JWT, созданный нашей Keycloak, и мы смогли проверить фао, содержащиеся на данном JWT с помощью аннотации spring.
Сейчас в Keycloak мы должны создать roles некоторые пользователи для тестирования.
Создание roles:
Создание пользователей:
Создание пользователя:
После того, как создан, в закладке” Credentials добавьте пароль, измените Temporary пра-ОФФ, и нажмите кнопку Set Password для создания пароля пользователя.
Теперь давайте setar a role пользователю. Создаем 2 roles (admin и user) и создаем 3 пользователей (администратора и пользователя). Мы setar a role согласно созданный пользователем. На аба Сопоставления ролей выберите роль без квадро Доступные роли Электронная группа кнопку Add selected под рамку:
Готово, давайте проверим. В почтальон, и в тот же request предыдущем уроке, мы будем менять формат маркер, который мы приказать. Pra – это альтернативный ключ grant_type пункт пароль . Кроме того, добавьте keys username и password с их значениями. В этом первом примере я искал маркер с пользователь пользователь команда eesti usuario выполняет роль пользователь . Nos конечные точки, требующие решения об обычной роли, которую играет терия, доступная для ао конечная точка /безопасность/имеет роль мас нао ао /безопасность/is-администратор . Идеальный… работает! Уже маркера пользователя admin что есть role admin доступ к /безопасность/is-администратор функция:
Хорошо, это он! Мы настроили Keycloak, чтобы позволить нам создавать токены, проверка подлинности пользователей и назначение им определенные права. Настроим наш проект spring для проверки этого токена и использовать данные, содержащиеся в JWT, чтобы дать авторизации пользователей в нашем приложении.
Первая часть этого учебника, это здесь и код, используемый, например, это в моем github
Большое объятие!
Оригинал: “https://dev.to/mmacorin/spring-boot-keycloak-protegendo-suas-apis-parte-2-5bb4”