我如何加载一个";“用户”;当提供JWT时,在micronaut后端

我如何加载一个";“用户”;当提供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

我有一个Micronaut微服务,它通过JsonWebTokens(JWT)处理身份验证

现在我想扩展这段代码。我的应用程序中的用户有一些额外的属性,如电子邮件、地址、团队ID等。我的数据库中有所有用户

如何在后端控制器方法中知道哪个用户对应于客户端发送的JWT

本指南包含Micronaut REST控制器的示例代码:

@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发送的所有内容
认证流 带有JWTs的默认oauth2流:

前提条件:用户已注册。用户名、哈希(密码)和furhter属性(电子邮件、地址、团队ID等)在后端是已知的

  • 客户端将用户名和密码发布到/login端点
  • 客户端接收JWT作为回报,并使用服务器机密签名
  • 在以后的每个请求中,客户机都会在Http报头中以承载方式发送此JWT
  • 后端验证JWT 当提供JWT时,如何在micronaut后端加载“用户”

    我正在读这篇文章,因为您计划加载某种类型的
    用户
    对象数据库并在控制器中访问它。 如果是这种情况,您需要挂接到创建身份验证实例的位置,以读取令牌的“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中。并且可以在my
    CustomAuthenticationProvider
    类中轻松设置:

    @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,身份验证){
    ...
    }
    
    请不要误会我。谢谢你