我如何加载一个";“用户”;当提供JWT时,在micronaut后端
我有一个Micronaut微服务,它通过JsonWebTokens(JWT)处理身份验证 现在我想扩展这段代码。我的应用程序中的用户有一些额外的属性,如电子邮件、地址、团队ID等。我的数据库中有所有用户 如何在后端控制器方法中知道哪个用户对应于客户端发送的JWT 本指南包含Micronaut REST控制器的示例代码:我如何加载一个";“用户”;当提供JWT时,在micronaut后端,jwt,micronaut,micronaut-security,Jwt,Micronaut,Micronaut Security,我有一个Micronaut微服务,它通过JsonWebTokens(JWT)处理身份验证 现在我想扩展这段代码。我的应用程序中的用户有一些额外的属性,如电子邮件、地址、团队ID等。我的数据库中有所有用户 如何在后端控制器方法中知道哪个用户对应于客户端发送的JWT 本指南包含Micronaut REST控制器的示例代码: @Secured(SecurityRule.IS_AUTHENTICATED) @Controller public class HomeController { @Pr
@Secured(SecurityRule.IS_AUTHENTICATED)
@Controller
public class HomeController {
@Produces(MediaType.TEXT_PLAIN)
@Get
public String index(Principal principal) {
return principal.getName();
}
}
我知道我可以从HttpRequest中获取主体的名称,即用户名。但是我如何获得我的附加属性呢
(也许我有点误解了JWT?)
- 这些是JWT的“声明”吗
- 我是否需要从DB表中按用户名加载相应的用户
- 如何验证发送的用户名是否实际有效
编辑更详细地描述我的用例: 我的用例的安全需求
- 不要向客户端公开有效信息
- 验证客户端(移动应用程序)通过REST发送的所有内容
用户
对象数据库并在控制器中访问它。
如果是这种情况,您需要挂接到创建身份验证实例的位置,以读取令牌的“sub”(用户名),然后从数据库中加载它
如何使用更多详细信息扩展身份验证属性
默认情况下,JWT身份验证是使用JwtAuthenticationFactory
创建的,更具体的默认实现是DefaultJwtAuthenticationFactory。如果您计划加载更多声明,可以通过替换它并创建扩展的JWTClaimsSet或您自己的身份验证接口实现来完成
如何访问jwt索赔
您需要检查SecurityService->getAuthentication()->getAttributes()
,它返回一个安全属性的映射,该映射表示序列化为映射的令牌
如何验证JWT是否有效 有一个基本的验证规则来检查令牌是否过期并正确签名,所有剩余的验证,特别是对于自定义声明和针对第三方来源的验证,都必须由您自己完成 如果您计划验证您的自定义声明,我已经在这个范围内打开了一个项目的源代码,请看一看 如何在发行期间使用额外的索赔扩展现有令牌 需要创建您自己的索赔生成器扩展
JWTClaimsSetGenerator
@Singleton
@替换(JWTclaimsetGenerator)
类CustomJWTClaimsSetGenerator扩展了JWTClaimsSetGenerator{
CustomJWTClaimsSetGenerator(令牌配置令牌配置,@Nullable JwtIdGenerator JwtIdGenerator,@Nullable ClaimsAudienceProvider ClaimsAudienceProvider){
超级(令牌配置、jwtIdGenerator、claimsAudienceProvider)
}
用UserDetails填充受保护的空(JWTClaimsSet.Builder,UserDetails UserDetails){
super.populateWithUserDetails(生成器,userDetails)
//你可以在这里申请海关索赔
builder.claim('email',userDetails.getAttributes().get(“email”);
}
}
我找到了一个解决方案。UserDetails.attributes
被序列化到JWT中。并且可以在myCustomAuthenticationProvider
类中轻松设置:
@Singleton
@Slf4j
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Override
public Publisher<AuthenticationResponse> authenticate(
@Nullable HttpRequest<?> httpRequest,
AuthenticationRequest<?, ?> authenticationRequest)
{
// ... autenticate the request here ...
// eg. via BasicAuth or Oauth 2.0 OneTimeToken
// then if valid:
return Flowable.create(emitter -> {
UserDetails userDetails = new UserDetails("sherlock", Collections.emptyList(), "sherlock@micronaut.example");
// These attributes will be serialized as custom claims in the JWT
Map attrs = CollectionUtils.mapOf("email", email, "teamId", teamId)
userDetails.setAttributes(attrs);
emitter.onNext(userDetails);
emitter.onComplete();
}, BackpressureStrategy.ERROR);
}
}
@Singleton
@Slf4j
公共类CustomAuthenticationProvider实现AuthenticationProvider{
@凌驾
公共发布者身份验证(
@可为空的HttpRequest HttpRequest,
AuthenticationRequest(身份验证请求)
{
//…在此处自动验证请求。。。
//例如,通过BasicAuth或Oauth 2.0 OneTimeToken
//然后,如果有效:
返回可流动。创建(发射器->{
UserDetails UserDetails=newuserdetails(“sherlock”,Collections.emptyList(),”sherlock@micronaut.example");
//这些属性将在JWT中序列化为自定义声明
Map attrs=CollectionUtils.mapOf(“电子邮件”,电子邮件,“团队ID”,团队ID)
userDetails.setAttributes(attrs);
emitter.onNext(用户详细信息);
emitter.onComplete();
},背压平衡误差);
}
}
在后端验证JWT时还有一些陷阱
Micronaut中的JWT必须包含“子”索赔。JWT规范不要求这样做,但Micronaut要求这样做。“sub”声明的值将成为所创建的UserDetails
对象的用户名
如果希望在后端验证JWT时将添加属性加载到这些UserDetails中,那么可以通过实现TokenValidator
来实现。但是(另一个pitfal)则必须将其顺序设置为大于micronaut的JwtTokenValidator
的值。您的订单必须大于0,否则您的TokenValidator将不会被调用
如何访问jwt索赔
如果您想从rest处理程序访问它们,只需在处理方法中添加io.micronaut.security.authentication.authentication
作为附加参数。范例
@Get(“/{fooId}”)
@安全(SecurityRule.IS_认证)
公共HttpResponse getFoo(长fooId,身份验证){
...
}
请不要误会我。谢谢你