0

使用 micronaut 创建受 micronaut-jwt 安全保护的休息端点

        @Post
        @IRequirement(resourceName = ClaimType.TAG_PRODUCT, permission = {ClaimValue.TAG_OWNER,ClaimValue.TAG_CREATOR,ClaimValue.TAG_MAINTAINER })
        Mono<MutableHttpResponse<?>> post(@Body @Valid ProductModel model){
        LOG.info(String.format("Creating new product"));
        return _iServiceBus.<ProductModel, Mono<ProductModel>>send(model).flatMap(item -> {
                    if (item != null) {
                        try {
                            return Mono.just(HttpResponse.created(item, new URI(String.format("/%s", item.id()))));
                        } catch (URISyntaxException e) {
                            return Mono.error(new GlobalException(e));
                        }
                    } else
                        return Mono.just(HttpResponse.serverError());
                }
        ).onErrorMap(throwable -> {
            throw new GlobalException(throwable);
        });}

安全模型

@Inherited
public @interface IRequirement {
    String resourceName();
    String[] permission();
}

安全规则

@Singleton
public class AuthorityHandler implements SecurityRule {
    @Override
    public Publisher<SecurityRuleResult> check(HttpRequest<?> request, @Nullable RouteMatch<?> routeMatch, @Nullable Authentication authentication) {
        if (routeMatch instanceof MethodBasedRouteMatch methodBasedRouteMatch) {
            if (methodBasedRouteMatch.hasAnnotation(IRequirement.class)) {
                AnnotationValue<IRequirement> requiredPermissionAnnotation = methodBasedRouteMatch.getAnnotation(IRequirement.class);
                Optional<String> resourceIdName = requiredPermissionAnnotation.stringValue( "resourceName");
                String[] permissions = requiredPermissionAnnotation.stringValues("permission");
                if (permissions.length > 0 && resourceIdName.isPresent() && authentication != null) {
                    Map<String, Object> identityClaims = authentication.getAttributes();
                    if (Arrays.stream(permissions).anyMatch(element ->  identityClaims.containsValue(element)))
                        return Mono.just(SecurityRuleResult.ALLOWED);
                    else
                        return Mono.just(SecurityRuleResult.REJECTED);
                }
            }
        }
        return Mono.just(SecurityRuleResult.UNKNOWN);
    }
}

上述端点受声明保护ownercreator并且maintainer

我正在使用身份服务器 4 ( https://github.com/IdentityServer/IdentityServer4 ) 来管理身份,并且当用户登录时,它在访问令牌中包含以下声明

{
  "nbf": 1641548846,
  "exp": 1641549046,
  "iss": "https://localhost:5001",
  "client_id": "Falcon_Identity_Server",
  "sub": "673533cc-7c0b-40f3-80ac-222696df385d",
  "auth_time": 1641548840,
  "idp": "local",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "673533cc-7c0b-40f3-80ac-222696df385d",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "admin@local.com",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "admin@local.com",
  "AspNet.Identity.SecurityStamp": "812aa4cb-b9f1-48ac-9e39-1f0dceb6f1c4",
  "identityserver": "owner",
  "fb_product": "owner",
  "fb_order": "owner",
  "fb_payment": "owner",
  "jti": "179683F5CCA01EB925B45B1CA6379080",
  "sid": "F1D9F917D34178EDAF7A5FD24948F89D",
  "iat": 1641548846,
  "scope": [
    "openid",
    "profile",
    "email"
  ],
  "amr": [
    "pwd"
  ]
}

上面的终点是寻找那些属性

"identityserver": "owner",
      "fb_product": "owner",
      "fb_order": "owner",
      "fb_payment": "owner",

对于运行真正的应用程序,它运行良好。我正在尝试使用 micronaut httpclient 编写测试用例。但不确定如何使用 micronaut 测试框架进行测试

我试过的东西

@Test
@DisplayName("Should create a JWT token")
void shouldCreateAJwtToken() {
    BearerAccessRefreshToken bearerAccessRefreshToken = null;
    UsernamePasswordCredentials creds = new UsernamePasswordCredentials("sherlock", "password");
    HttpRequest request = HttpRequest.POST("/login", creds);
    HttpResponse<BearerAccessRefreshToken> rsp = client.toBlocking().exchange(request, BearerAccessRefreshToken.class);
    bearerAccessRefreshToken = rsp.body();

}

它创建一个令牌,但不包含上述访问令牌所需的所有验证。

我们如何在 micronaut 中进行受 JWT 令牌保护的休息端点单元测试

身份验证提供程序

@Singleton
@Requires(env = Environment.TEST)
public record AuthenticationProviderUserPasswordFixture() implements AuthenticationProvider {
    @Override
    public Publisher<AuthenticationResponse> authenticate(HttpRequest<?> httpRequest, AuthenticationRequest<?, ?> authenticationRequest) {
        return Flux.create(emitter -> {
            if (authenticationRequest.getIdentity().equals("sherlock") && authenticationRequest.getSecret().equals("password")) {
                emitter.next(AuthenticationResponse.success((String) authenticationRequest.getIdentity(), List.of("roles1", "roles2")));
                emitter.complete();
            } else {
                emitter.error(AuthenticationResponse.exception());
            }
        }, FluxSink.OverflowStrategy.ERROR);
    }
}
4

1 回答 1

0

AuthenticationProvider在实现并返回模拟身份验证的测试源文件夹中创建一个类。可以使用您想要的任何属性填充该身份验证对象。

于 2022-01-13T04:51:38.660 回答