Блог первоначально опубликован в моем блоге 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
List auths = 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”