micronaut 安全中的自定义 JWT 过期
Custom JWT expiration in micronaut security
JWT的过期时间可以通过配置micronaut.security.token.jwt.generator.access-token-expiration来设置。
是否可以为单独发行的 JWT 令牌设置自定义值?搜索文档我没有找到任何有用的信息,除非您可以将 BearerTokenRenderer
和 return 替换为自定义响应。
public AccessRefreshToken render(Integer expiresIn, String accessToken, @Nullable String refreshToken) {
return new AccessRefreshToken(accessToken, refreshToken, BEARER_TOKEN_TYPE, ***customValue**);
}
在这种情况下 return 为 expires_in
设置不同的值是否可行?
根据 micronaut documentation - pt 9.3.5
您可以将 ClaimGenerator 替换为您自己的:
ClaimGenerator
其中有一个带参数的方法Integer expiration
您可以使用 @Replaces
注释替换 类,如下所述:
https://micronaut-projects.github.io/micronaut-core/latest/guide/#replaces
希望能解决您的问题
解决方案是扩展 JwTClaimsSet 生成器
@Replaces(JWTClaimsSetGenerator.class)
@Singleton
public class CustomClaimsGenerator extends JWTClaimsSetGenerator {
private static final Logger LOG = LoggerFactory.getLogger(CustomClaimsGenerator.class);
private static final String ROLES_KEY = "rolesKey";
private final TokenConfiguration tokenConfiguration;
private final JwtIdGenerator jwtIdGenerator;
private final ClaimsAudienceProvider claimsAudienceProvider;
private final String appName;
/**
* @param tokenConfiguration Token Configuration
* @param jwtIdGenerator Generator which creates unique JWT ID
* @param claimsAudienceProvider Provider which identifies the recipients that the JWT is intended for.
* @param applicationConfiguration The application configuration
*/
public CustomClaimsGenerator(TokenConfiguration tokenConfiguration,@Nullable JwtIdGenerator jwtIdGenerator, @Nullable ClaimsAudienceProvider claimsAudienceProvider, ApplicationConfiguration applicationConfiguration) {
super(tokenConfiguration, jwtIdGenerator, claimsAudienceProvider, applicationConfiguration);
this.tokenConfiguration = tokenConfiguration;
this.jwtIdGenerator = jwtIdGenerator;
this.claimsAudienceProvider = claimsAudienceProvider;
this.appName = applicationConfiguration != null ? applicationConfiguration.getName().orElse(Environment.MICRONAUT) : Environment.MICRONAUT;
}
/**
* @param authentication Authenticated user's representation.
* @param expiration expiration time in seconds
* @return The authentication claims
*/
@Override
public Map<String, Object> generateClaims(Authentication authentication, @Nullable Integer expiration) {
expiration = 1000; //works with this value
JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder();
populateIat(builder);
populateExp(builder, 15);
populateJti(builder);
populateIss(builder);
populateAud(builder);
populateNbf(builder);
populateWithAuthentication(builder, authentication);
if (LOG.isDebugEnabled()) {
LOG.debug("Generated claim set: {}", builder.build().toJSONObject());
}
return builder.build().getClaims();
}
/**
* Populates iss claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.1">iss (Issuer) Claim</a>
*/
protected void populateIss(JWTClaimsSet.Builder builder) {
if (appName != null) {
builder.issuer(appName); // iss
}
}
/**
* Populates sub claim.
*
* @param builder The Claims Builder
* @param authentication Authenticated user's representation.
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.2">sub (Subject) Claim</a>
*/
protected void populateSub(JWTClaimsSet.Builder builder, Authentication authentication) {
builder.subject(authentication.getName()); // sub
}
/**
* Populates aud claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.3">aud (Audience) Claim</a>
*/
protected void populateAud(JWTClaimsSet.Builder builder) {
if (claimsAudienceProvider != null) {
builder.audience(claimsAudienceProvider.audience()); // aud
}
}
/**
* Populates exp claim.
*
* @param builder The Claims Builder
* @param expiration expiration time in seconds
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.4">exp (ExpirationTime) Claim</a>
*/
protected void populateExp(JWTClaimsSet.Builder builder, @Nullable Integer expiration) {
if (expiration != null) {
LOG.debug("Setting expiration to {}", expiration);
System.out.print(Date.from(Instant.now().plus(expiration, ChronoUnit.SECONDS)));
builder.expirationTime(Date.from(Instant.now().plus(expiration, ChronoUnit.SECONDS))); // exp
}
}
/**
* Populates nbf claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.5">nbf (Not Before) Claim</a>
*/
protected void populateNbf(JWTClaimsSet.Builder builder) {
builder.notBeforeTime(new Date()); // nbf
}
/**
* Populates iat claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.6">iat (Issued At) Claim</a>
*/
protected void populateIat(JWTClaimsSet.Builder builder) {
builder.issueTime(new Date()); // iat
}
/**
* Populates jti claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.7">jti (JWT ID) Claim</a>
*/
protected void populateJti(JWTClaimsSet.Builder builder) {
if (jwtIdGenerator != null) {
builder.jwtID(jwtIdGenerator.generateJtiClaim()); // jti
}
}
/**
* Populates Claims with Authentication object.
*
* @param builder the Claims Builder
* @param authentication Authenticated user's representation.
*/
protected void populateWithAuthentication(JWTClaimsSet.Builder builder, Authentication authentication) {
populateSub(builder, authentication);
authentication.getAttributes().forEach(builder::claim);
String rolesKey = tokenConfiguration.getRolesName();
if (!rolesKey.equalsIgnoreCase(TokenConfiguration.DEFAULT_ROLES_NAME)) {
builder.claim(ROLES_KEY, rolesKey);
}
builder.claim(rolesKey, authentication.getRoles());
}
/**
* @param oldClaims The old claims to use as a base in the new token generation.
* @param expiration expiration time in seconds
* @return Instance of {@link JWTClaimsSet}
*/
@Override
public Map<String, Object> generateClaimsSet(Map<String, ?> oldClaims, Integer expiration) {
JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder();
List<String> excludedClaims = Arrays.asList(JwtClaims.EXPIRATION_TIME, JwtClaims.ISSUED_AT, JwtClaims.NOT_BEFORE);
for (String k : oldClaims.keySet()
.stream()
.filter(p -> !excludedClaims.contains(p))
.collect(Collectors.toList())) {
builder.claim(k, oldClaims.get(k));
}
populateExp(builder, expiration);
populateIat(builder);
populateNbf(builder);
return builder.build().getClaims();
}
}
JWT的过期时间可以通过配置micronaut.security.token.jwt.generator.access-token-expiration来设置。
是否可以为单独发行的 JWT 令牌设置自定义值?搜索文档我没有找到任何有用的信息,除非您可以将 BearerTokenRenderer
和 return 替换为自定义响应。
public AccessRefreshToken render(Integer expiresIn, String accessToken, @Nullable String refreshToken) {
return new AccessRefreshToken(accessToken, refreshToken, BEARER_TOKEN_TYPE, ***customValue**);
}
在这种情况下 return 为 expires_in
设置不同的值是否可行?
根据 micronaut documentation - pt 9.3.5
您可以将 ClaimGenerator 替换为您自己的: ClaimGenerator
其中有一个带参数的方法Integer expiration
您可以使用 @Replaces
注释替换 类,如下所述:
https://micronaut-projects.github.io/micronaut-core/latest/guide/#replaces
希望能解决您的问题
解决方案是扩展 JwTClaimsSet 生成器
@Replaces(JWTClaimsSetGenerator.class)
@Singleton
public class CustomClaimsGenerator extends JWTClaimsSetGenerator {
private static final Logger LOG = LoggerFactory.getLogger(CustomClaimsGenerator.class);
private static final String ROLES_KEY = "rolesKey";
private final TokenConfiguration tokenConfiguration;
private final JwtIdGenerator jwtIdGenerator;
private final ClaimsAudienceProvider claimsAudienceProvider;
private final String appName;
/**
* @param tokenConfiguration Token Configuration
* @param jwtIdGenerator Generator which creates unique JWT ID
* @param claimsAudienceProvider Provider which identifies the recipients that the JWT is intended for.
* @param applicationConfiguration The application configuration
*/
public CustomClaimsGenerator(TokenConfiguration tokenConfiguration,@Nullable JwtIdGenerator jwtIdGenerator, @Nullable ClaimsAudienceProvider claimsAudienceProvider, ApplicationConfiguration applicationConfiguration) {
super(tokenConfiguration, jwtIdGenerator, claimsAudienceProvider, applicationConfiguration);
this.tokenConfiguration = tokenConfiguration;
this.jwtIdGenerator = jwtIdGenerator;
this.claimsAudienceProvider = claimsAudienceProvider;
this.appName = applicationConfiguration != null ? applicationConfiguration.getName().orElse(Environment.MICRONAUT) : Environment.MICRONAUT;
}
/**
* @param authentication Authenticated user's representation.
* @param expiration expiration time in seconds
* @return The authentication claims
*/
@Override
public Map<String, Object> generateClaims(Authentication authentication, @Nullable Integer expiration) {
expiration = 1000; //works with this value
JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder();
populateIat(builder);
populateExp(builder, 15);
populateJti(builder);
populateIss(builder);
populateAud(builder);
populateNbf(builder);
populateWithAuthentication(builder, authentication);
if (LOG.isDebugEnabled()) {
LOG.debug("Generated claim set: {}", builder.build().toJSONObject());
}
return builder.build().getClaims();
}
/**
* Populates iss claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.1">iss (Issuer) Claim</a>
*/
protected void populateIss(JWTClaimsSet.Builder builder) {
if (appName != null) {
builder.issuer(appName); // iss
}
}
/**
* Populates sub claim.
*
* @param builder The Claims Builder
* @param authentication Authenticated user's representation.
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.2">sub (Subject) Claim</a>
*/
protected void populateSub(JWTClaimsSet.Builder builder, Authentication authentication) {
builder.subject(authentication.getName()); // sub
}
/**
* Populates aud claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.3">aud (Audience) Claim</a>
*/
protected void populateAud(JWTClaimsSet.Builder builder) {
if (claimsAudienceProvider != null) {
builder.audience(claimsAudienceProvider.audience()); // aud
}
}
/**
* Populates exp claim.
*
* @param builder The Claims Builder
* @param expiration expiration time in seconds
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.4">exp (ExpirationTime) Claim</a>
*/
protected void populateExp(JWTClaimsSet.Builder builder, @Nullable Integer expiration) {
if (expiration != null) {
LOG.debug("Setting expiration to {}", expiration);
System.out.print(Date.from(Instant.now().plus(expiration, ChronoUnit.SECONDS)));
builder.expirationTime(Date.from(Instant.now().plus(expiration, ChronoUnit.SECONDS))); // exp
}
}
/**
* Populates nbf claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.5">nbf (Not Before) Claim</a>
*/
protected void populateNbf(JWTClaimsSet.Builder builder) {
builder.notBeforeTime(new Date()); // nbf
}
/**
* Populates iat claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.6">iat (Issued At) Claim</a>
*/
protected void populateIat(JWTClaimsSet.Builder builder) {
builder.issueTime(new Date()); // iat
}
/**
* Populates jti claim.
*
* @param builder The Claims Builder
* @see <a href="https://tools.ietf.org/html/rfc7519#section-4.1.7">jti (JWT ID) Claim</a>
*/
protected void populateJti(JWTClaimsSet.Builder builder) {
if (jwtIdGenerator != null) {
builder.jwtID(jwtIdGenerator.generateJtiClaim()); // jti
}
}
/**
* Populates Claims with Authentication object.
*
* @param builder the Claims Builder
* @param authentication Authenticated user's representation.
*/
protected void populateWithAuthentication(JWTClaimsSet.Builder builder, Authentication authentication) {
populateSub(builder, authentication);
authentication.getAttributes().forEach(builder::claim);
String rolesKey = tokenConfiguration.getRolesName();
if (!rolesKey.equalsIgnoreCase(TokenConfiguration.DEFAULT_ROLES_NAME)) {
builder.claim(ROLES_KEY, rolesKey);
}
builder.claim(rolesKey, authentication.getRoles());
}
/**
* @param oldClaims The old claims to use as a base in the new token generation.
* @param expiration expiration time in seconds
* @return Instance of {@link JWTClaimsSet}
*/
@Override
public Map<String, Object> generateClaimsSet(Map<String, ?> oldClaims, Integer expiration) {
JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder();
List<String> excludedClaims = Arrays.asList(JwtClaims.EXPIRATION_TIME, JwtClaims.ISSUED_AT, JwtClaims.NOT_BEFORE);
for (String k : oldClaims.keySet()
.stream()
.filter(p -> !excludedClaims.contains(p))
.collect(Collectors.toList())) {
builder.claim(k, oldClaims.get(k));
}
populateExp(builder, expiration);
populateIat(builder);
populateNbf(builder);
return builder.build().getClaims();
}
}