Блог первоначально опубликован в моем блоге js blogs.github.io
- Вступление
- Используемые технологии
- Схема последовательности потока OAuth2
- Магазин Jwttoken
Вступление
В этом сообщении в блоге будет продемонстрирована интеграция spring-security и angular JS с использованием токена JWT. В моем предыдущем блоге объясняется, как мы можем настроить классы для интеграции spring security с angular. Я рекомендую вам посмотреть мой предыдущий видеоурок, потому что этот урок является дополнением к этому видео.
Весенняя безопасность с использованием OAuth2 с Angular JS
Джитендра Сингх Бишт ・ 27 июня ・ 1 минута читать
В этом видеоуроке я создал TokenStore
класс для хранения токена, который я перепишу в этом блоге для генерации токенов JWT.
Используемые технологии
- Ява
- Пружинный ботинок
- Пружинная защита
- Угловой JS 8
Схема последовательности потока OAuth2
Магазин Jwttoken
В этом видеоуроке я создал хранилище токенов на основе хэш-карты. Теперь мы собираемся перезаписать этот класс и создадим одну реализацию на основе JWT.
package com.demo.security.config; import com.nimbusds.jose.JOSEObjectType; import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jose.JWSHeader; import com.nimbusds.jose.crypto.ECDSASigner; import com.nimbusds.jose.jwk.Curve; import com.nimbusds.jose.jwk.ECKey; import com.nimbusds.jose.jwk.gen.ECKeyGenerator; import com.nimbusds.jwt.JWT; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.oauth2.core.user.DefaultOAuth2User; import org.springframework.stereotype.Component; import java.security.interfaces.ECPrivateKey; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalUnit; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Component public class JwtTokenStore implements ITokenStore { // 1 private final String tokenSignKey = "c5d4d70419bd4909a1e502812c6e1f2b"; // 2 private final String REG_ID = "clientRegistrationId"; private final String NAMED_KEY = "namedAttributeKey"; private final String AUTHORITIES = "authorities"; private final String ATTRIBUTES = "attributes"; // 3 public String generateToken( Authentication authentication ) throws Exception { OAuth2AuthenticationToken token = ( OAuth2AuthenticationToken ) authentication; DefaultOAuth2User userDetails = ( DefaultOAuth2User ) token.getPrincipal(); // 4 Listauths = userDetails.getAuthorities() .stream() .map( GrantedAuthority::getAuthority ) .collect( Collectors.toList()); // 5 JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() .subject( userDetails.getAttribute("id").toString()) .expirationTime( getDate( 5, ChronoUnit.HOURS ) ) .claim( NAMED_KEY, "name" ) .claim( ATTRIBUTES, userDetails.getAttributes() ) .claim( AUTHORITIES, auths ) .claim( REG_ID, token.getAuthorizedClientRegistrationId() ) .build(); // 6 ECKey key = new ECKeyGenerator( Curve.P_256 ).keyID( tokenSignKey ).generate(); JWSHeader h = new JWSHeader.Builder( JWSAlgorithm.ES256 ) .type( JOSEObjectType.JWT ) .keyID( key.getKeyID() ) .build(); SignedJWT jwt = new SignedJWT( h, claimsSet ); // 7 jwt.sign( new ECDSASigner( ( ECPrivateKey ) key.toPrivateKey() ) ); return jwt.serialize(); } // 8 public Authentication getAuth( String jwt ) throws Exception { SignedJWT signedJWT = SignedJWT.parse( jwt ); // 9 validateJwt( signedJWT ); JWTClaimsSet claimsSet = signedJWT.getJWTClaimsSet(); // 10 String clientRegistrationId = (String ) claimsSet.getClaim( REG_ID ); String namedAttributeKey = (String) claimsSet.getClaim( NAMED_KEY ); Map attributes = (Map )claimsSet.getClaim( ATTRIBUTES ); Collection extends GrantedAuthority > authorities =( (List ) claimsSet.getClaim( AUTHORITIES )) .stream().map( SimpleGrantedAuthority::new ).collect( Collectors.toSet()); // 11 return new OAuth2AuthenticationToken( new DefaultOAuth2User( authorities, attributes, namedAttributeKey ), authorities, clientRegistrationId ); } private static Date getDate( long amount, TemporalUnit unit ) { return Date.from( LocalDateTime.now() .plus( amount, unit ) .atZone( ZoneId.systemDefault() ) .toInstant() ); } private void validateJwt( JWT jwt ) throws Exception { // 12 if(jwt.getJWTClaimsSet().getExpirationTime().before( new Date() )){ throw new RuntimeException("Token Expired!!"); } // Add validation logic here.. } }
В приведенную выше кодовую базу я добавил номера комментариев, которые я собираюсь объяснить здесь.
- Ключ подписи токена будет использоваться для подписи JWT. Вы можете использовать свой собственный ключ.
- Атрибуты, которые я собираюсь получить от объекта аутентификации и поместить их в JWT, который я буду использовать позже для создания объекта аутентификации.
- Метод generateToken примет объект аутентификации и создаст из него токен JWT.
- Собирая все имена авторитетов.
- Подготовка утверждений JWT с такими значениями, как Тема, Полномочия, атрибуты, Именованный ключ атрибута (требуется для DefaultOAuth2User) и время истечения срока действия токена
- Подготовьте ключ подписи для подписи токена JWT.
- Подпишите жетон и возвращайтесь.
- Метод getAuth принимает токен JWT и подготавливает объект аутентификации из действительного токена.
- Проверка токена JWT в настоящее время я проверяю только время истечения срока действия, но вы можете добавить свою собственную логику проверки.
- Получите необходимые объекты из утверждений JWT, которые будут использоваться для подготовки токена аутентификации.
- Подготовьте и верните действительный
Токен аутентификации OAuth2
. - Сверка времени истечения срока действия с текущим временем.
Работающий код можно найти здесь .
Оригинал: “https://dev.to/jeetmp3/spring-security-using-oauth2-with-angularjs-jwt-4nmd”