扩展 Micronaut CustomJWTClaimsSetGenerator 以提供所有属性
Extend Micronaut CustomJWTClaimsSetGenerator to provide all attributes
我有以下两个 class 提供 JWT 身份验证机制。
CustomDelegatingAuthenticationProvider
@Singleton
@Replaces(value = DelegatingAuthenticationProvider.class)
public class CustomDelegatingAuthenticationProvider extends DelegatingAuthenticationProvider {
/**
* @param userFetcher Fetches users from persistence
* @param passwordEncoder Collaborator which checks if a raw password matches an encoded password
* @param authoritiesFetcher Fetches authorities for a particular user
*/
public CustomDelegatingAuthenticationProvider(UserFetcher userFetcher, PasswordEncoder passwordEncoder, AuthoritiesFetcher authoritiesFetcher) {
super(userFetcher, passwordEncoder, authoritiesFetcher);
}
@Override
protected Publisher<AuthenticationResponse> createSuccessfulAuthenticationResponse(AuthenticationRequest authenticationRequest, UserState userState) {
if (userState instanceof UserMember) {
UserMember user = (UserMember) userState;
return Flowable
.fromPublisher(authoritiesFetcher.findAuthoritiesByUsername(user.getUsername()))
.map(authorities -> new HDSUser(user.getUsername(), authorities, user.getId()));
}
return super.createSuccessfulAuthenticationResponse(authenticationRequest, userState);
}
}
CustomJWTClaimsSetGenerator
@Singleton
@Replaces(value = JWTClaimsSetGenerator.class)
public class CustomJWTClaimsSetGenerator extends JWTClaimsSetGenerator {
CustomJWTClaimsSetGenerator(TokenConfiguration tokenConfiguration, @Nullable JwtIdGenerator jwtIdGenerator, @Nullable ClaimsAudienceProvider claimsAudienceProvider) {
super(tokenConfiguration, jwtIdGenerator, claimsAudienceProvider);
}
protected void populateWithUserDetails(JWTClaimsSet.Builder builder, UserDetails userDetails) {
super.populateWithUserDetails(builder, userDetails);
if (userDetails instanceof HDSUser) {
builder.claim("userId", ((HDSUser) userDetails).getId());
}
}
}
对客户端的默认响应如下所示:
我的问题。如何将 class 扩展到 return 所有用户属性?除了用户名,我还想拥有用户 ID。
更新
收集DB id
的HDS用户class
@CompileStatic
public class HDSUser extends UserDetails {
private long id;
public HDSUser(String username, Collection<String> roles, long id) {
super(username, roles);
this.id = id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
要扩展返回的数据,您需要扩展(实现自定义)TokenRenderer
以及 AccessRefreshToken
的自定义版本。
作为一个简单的示例,请参阅以下代码片段,它将使用 userId
字段扩展默认访问令牌负载。
首先,创建自定义 AccessRefreshToken
class,其中包含其他必填字段。
@Introspected
@Getter
@Setter
public class CustomAccessRefreshToken extends BearerAccessRefreshToken {
// the new field which will be in the response
private String userId;
public CustomAccessRefreshToken(String username,
Collection<String> roles,
Integer expiresIn,
String accessToken,
String refreshToken,
String tokenType
) {
super(username, roles, expiresIn, accessToken, refreshToken, tokenType);
}
}
接下来,我们将需要一个 TokenRenderer
,底层子系统将使用它来生成我们的自定义令牌。
@Singleton
@Replaces(value = BearerTokenRenderer.class)
public class CustomTokenRenderer implements TokenRenderer {
private static final String BEARER_TOKEN_TYPE = HttpHeaderValues.AUTHORIZATION_PREFIX_BEARER;
@Override
public AccessRefreshToken render(Integer expiresIn, String accessToken, @Nullable String refreshToken) {
return new AccessRefreshToken(accessToken, refreshToken, BEARER_TOKEN_TYPE, expiresIn);
}
@Override
public AccessRefreshToken render(Authentication authentication, Integer expiresIn, String accessToken, @Nullable String refreshToken) {
CustomAccessRefreshToken token = new CustomAccessRefreshToken(authentication.getName(), authentication.getRoles(), expiresIn, accessToken, refreshToken, BEARER_TOKEN_TYPE);
// here just take the user data from Authentication object or access any other service
token.setUserId("Some user id");
return token;
}
}
就是这样 )) 只需按照您想要的方式实施 render()
方法,并根据需要添加尽可能多的自定义字段。
给定示例的响应如下所示
{
"username": "sherlock",
"userId": "Some user id",
"access_token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzaGVybG9jayIsIm5iZiI6MTYzNjk5MTgzMSwicm9sZXMiOltdLCJpc3MiOiJtaWNyb25hdXRndWlkZSIsImV4cCI6MTYzNjk5NTQzMSwiaWF0IjoxNjM2OTkxODMxfQ.Cat1CTsUZkCj-OHGafiefNm1snPsALoaNw9y2xwF5Pw",
"token_type": "Bearer",
"expires_in": 3600
}
如果您使用的是旧版本的 Micronaut v1.x,TokenRenderer 将如下所示。
@Singleton
@Replaces(value = BearerTokenRenderer.class)
public class CustomTokenRenderer implements TokenRenderer {
private static final String BEARER_TOKEN_TYPE = HttpHeaderValues.AUTHORIZATION_PREFIX_BEARER;
public AccessRefreshToken render(Integer expiresIn, String accessToken, String refreshToken) {
return new AccessRefreshToken(accessToken, refreshToken, BEARER_TOKEN_TYPE, expiresIn);
}
public AccessRefreshToken render(UserDetails userDetails, Integer expiresIn, String accessToken, String refreshToken) {
CustomAccessRefreshToken token = new CustomAccessRefreshToken(userDetails.getUsername(), userDetails.getRoles(), expiresIn, accessToken, refreshToken, BEARER_TOKEN_TYPE);
token.setUserId("Some user id, Some user id");
return token;
}
}
我有以下两个 class 提供 JWT 身份验证机制。
CustomDelegatingAuthenticationProvider
@Singleton
@Replaces(value = DelegatingAuthenticationProvider.class)
public class CustomDelegatingAuthenticationProvider extends DelegatingAuthenticationProvider {
/**
* @param userFetcher Fetches users from persistence
* @param passwordEncoder Collaborator which checks if a raw password matches an encoded password
* @param authoritiesFetcher Fetches authorities for a particular user
*/
public CustomDelegatingAuthenticationProvider(UserFetcher userFetcher, PasswordEncoder passwordEncoder, AuthoritiesFetcher authoritiesFetcher) {
super(userFetcher, passwordEncoder, authoritiesFetcher);
}
@Override
protected Publisher<AuthenticationResponse> createSuccessfulAuthenticationResponse(AuthenticationRequest authenticationRequest, UserState userState) {
if (userState instanceof UserMember) {
UserMember user = (UserMember) userState;
return Flowable
.fromPublisher(authoritiesFetcher.findAuthoritiesByUsername(user.getUsername()))
.map(authorities -> new HDSUser(user.getUsername(), authorities, user.getId()));
}
return super.createSuccessfulAuthenticationResponse(authenticationRequest, userState);
}
}
CustomJWTClaimsSetGenerator
@Singleton
@Replaces(value = JWTClaimsSetGenerator.class)
public class CustomJWTClaimsSetGenerator extends JWTClaimsSetGenerator {
CustomJWTClaimsSetGenerator(TokenConfiguration tokenConfiguration, @Nullable JwtIdGenerator jwtIdGenerator, @Nullable ClaimsAudienceProvider claimsAudienceProvider) {
super(tokenConfiguration, jwtIdGenerator, claimsAudienceProvider);
}
protected void populateWithUserDetails(JWTClaimsSet.Builder builder, UserDetails userDetails) {
super.populateWithUserDetails(builder, userDetails);
if (userDetails instanceof HDSUser) {
builder.claim("userId", ((HDSUser) userDetails).getId());
}
}
}
对客户端的默认响应如下所示:
我的问题。如何将 class 扩展到 return 所有用户属性?除了用户名,我还想拥有用户 ID。
更新
收集DB id
的HDS用户class@CompileStatic
public class HDSUser extends UserDetails {
private long id;
public HDSUser(String username, Collection<String> roles, long id) {
super(username, roles);
this.id = id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
要扩展返回的数据,您需要扩展(实现自定义)TokenRenderer
以及 AccessRefreshToken
的自定义版本。
作为一个简单的示例,请参阅以下代码片段,它将使用 userId
字段扩展默认访问令牌负载。
首先,创建自定义 AccessRefreshToken
class,其中包含其他必填字段。
@Introspected
@Getter
@Setter
public class CustomAccessRefreshToken extends BearerAccessRefreshToken {
// the new field which will be in the response
private String userId;
public CustomAccessRefreshToken(String username,
Collection<String> roles,
Integer expiresIn,
String accessToken,
String refreshToken,
String tokenType
) {
super(username, roles, expiresIn, accessToken, refreshToken, tokenType);
}
}
接下来,我们将需要一个 TokenRenderer
,底层子系统将使用它来生成我们的自定义令牌。
@Singleton
@Replaces(value = BearerTokenRenderer.class)
public class CustomTokenRenderer implements TokenRenderer {
private static final String BEARER_TOKEN_TYPE = HttpHeaderValues.AUTHORIZATION_PREFIX_BEARER;
@Override
public AccessRefreshToken render(Integer expiresIn, String accessToken, @Nullable String refreshToken) {
return new AccessRefreshToken(accessToken, refreshToken, BEARER_TOKEN_TYPE, expiresIn);
}
@Override
public AccessRefreshToken render(Authentication authentication, Integer expiresIn, String accessToken, @Nullable String refreshToken) {
CustomAccessRefreshToken token = new CustomAccessRefreshToken(authentication.getName(), authentication.getRoles(), expiresIn, accessToken, refreshToken, BEARER_TOKEN_TYPE);
// here just take the user data from Authentication object or access any other service
token.setUserId("Some user id");
return token;
}
}
就是这样 )) 只需按照您想要的方式实施 render()
方法,并根据需要添加尽可能多的自定义字段。
给定示例的响应如下所示
{
"username": "sherlock",
"userId": "Some user id",
"access_token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzaGVybG9jayIsIm5iZiI6MTYzNjk5MTgzMSwicm9sZXMiOltdLCJpc3MiOiJtaWNyb25hdXRndWlkZSIsImV4cCI6MTYzNjk5NTQzMSwiaWF0IjoxNjM2OTkxODMxfQ.Cat1CTsUZkCj-OHGafiefNm1snPsALoaNw9y2xwF5Pw",
"token_type": "Bearer",
"expires_in": 3600
}
如果您使用的是旧版本的 Micronaut v1.x,TokenRenderer 将如下所示。
@Singleton
@Replaces(value = BearerTokenRenderer.class)
public class CustomTokenRenderer implements TokenRenderer {
private static final String BEARER_TOKEN_TYPE = HttpHeaderValues.AUTHORIZATION_PREFIX_BEARER;
public AccessRefreshToken render(Integer expiresIn, String accessToken, String refreshToken) {
return new AccessRefreshToken(accessToken, refreshToken, BEARER_TOKEN_TYPE, expiresIn);
}
public AccessRefreshToken render(UserDetails userDetails, Integer expiresIn, String accessToken, String refreshToken) {
CustomAccessRefreshToken token = new CustomAccessRefreshToken(userDetails.getUsername(), userDetails.getRoles(), expiresIn, accessToken, refreshToken, BEARER_TOKEN_TYPE);
token.setUserId("Some user id, Some user id");
return token;
}
}