使用 JUnit 5 测试 Micronaut 3.3.4 的身份验证为空
尝试使用 JUnit 测试通过 micronaut 安全性保护控制器,将身份验证设置为 NULL。
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@MicronautTest
public class ProductCreateTest extends TestContainerFixture {
private BearerAccessRefreshToken bearerAccessRefreshToken = null;
@Inject
@Client("/")
HttpClient client;
private ProductModel productModel;
@Test
@Order(1)
@DisplayName("Should create a JWT token")
void shouldCreateAJwtToken() {
UsernamePasswordCredentials creds = new UsernamePasswordCredentials("[email protected]", "RockStar.1");
HttpRequest request = HttpRequest.POST("/login", creds);
HttpResponse<BearerAccessRefreshToken> rsp = client.toBlocking().exchange(request, BearerAccessRefreshToken.class);
bearerAccessRefreshToken = rsp.body();
}
@Test
@Order(2)
@DisplayName("Should create the product")
void shouldCreateTheProduct() {
this.productModel = new ProductModel(
null,
Optional.of(true),
Optional.of(false),
"Nike shirt",
"Nike shirt description",
Optional.of(new CategoryModel(new ObjectId().toString(), "Men", "Men")),
Optional.of(new SubCategoryModel(new ObjectId().toString(), "Men", "Men")),
Optional.of(new VendorModel(new ObjectId().toString(), "Men", "Men")),
Optional.of(List.of(new SelectOptionModel("Shirt", "Shirt"))),
Optional.of(false)
);
HttpRequest request = HttpRequest.POST("/product", this.productModel)
.header("Authorization",bearerAccessRefreshToken.getAccessToken());
HttpResponse<ProductModel> rsp = client.toBlocking().exchange(request, ProductModel.class);
var item = rsp.body();
}
}
身份验证提供程序
@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("[email protected]") && authenticationRequest.getSecret().equals("RockStar.1")) {
emitter.next(AuthenticationResponse.success((String) authenticationRequest.getIdentity(), List.of("roles1", "roles2")));
emitter.complete();
} else {
emitter.error(AuthenticationResponse.exception());
}
}, FluxSink.OverflowStrategy.ERROR);
}
}
控制器定义
@Post
@IRequirement(resourceName = ClaimType.TAG_PRODUCT, permission = {ClaimValue.TAG_OWNER,ClaimValue.TAG_CREATOR,ClaimValue.TAG_MAINTAINER })
Mono<MutableHttpResponse<?>> post(@Body @Valid ProductModel model);
安全规则
@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);
}
}
安全规则中的检查方法 身份验证身份验证
为空。但是,从身份验证提供者处,我已成功进行身份验证。
Trying to protect the controller with micronaut security using JUnit testing, getting authentication as NULL.
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@MicronautTest
public class ProductCreateTest extends TestContainerFixture {
private BearerAccessRefreshToken bearerAccessRefreshToken = null;
@Inject
@Client("/")
HttpClient client;
private ProductModel productModel;
@Test
@Order(1)
@DisplayName("Should create a JWT token")
void shouldCreateAJwtToken() {
UsernamePasswordCredentials creds = new UsernamePasswordCredentials("[email protected]", "RockStar.1");
HttpRequest request = HttpRequest.POST("/login", creds);
HttpResponse<BearerAccessRefreshToken> rsp = client.toBlocking().exchange(request, BearerAccessRefreshToken.class);
bearerAccessRefreshToken = rsp.body();
}
@Test
@Order(2)
@DisplayName("Should create the product")
void shouldCreateTheProduct() {
this.productModel = new ProductModel(
null,
Optional.of(true),
Optional.of(false),
"Nike shirt",
"Nike shirt description",
Optional.of(new CategoryModel(new ObjectId().toString(), "Men", "Men")),
Optional.of(new SubCategoryModel(new ObjectId().toString(), "Men", "Men")),
Optional.of(new VendorModel(new ObjectId().toString(), "Men", "Men")),
Optional.of(List.of(new SelectOptionModel("Shirt", "Shirt"))),
Optional.of(false)
);
HttpRequest request = HttpRequest.POST("/product", this.productModel)
.header("Authorization",bearerAccessRefreshToken.getAccessToken());
HttpResponse<ProductModel> rsp = client.toBlocking().exchange(request, ProductModel.class);
var item = rsp.body();
}
}
Authentication Provider
@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("[email protected]") && authenticationRequest.getSecret().equals("RockStar.1")) {
emitter.next(AuthenticationResponse.success((String) authenticationRequest.getIdentity(), List.of("roles1", "roles2")));
emitter.complete();
} else {
emitter.error(AuthenticationResponse.exception());
}
}, FluxSink.OverflowStrategy.ERROR);
}
}
Controller defination
@Post
@IRequirement(resourceName = ClaimType.TAG_PRODUCT, permission = {ClaimValue.TAG_OWNER,ClaimValue.TAG_CREATOR,ClaimValue.TAG_MAINTAINER })
Mono<MutableHttpResponse<?>> post(@Body @Valid ProductModel model);
Security Rule
@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);
}
}
In the security rule the check method The Authentication authentication
is null. However, from the Authentication Provider, I have successful authentication.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
将安全日志添加到 logback.xml 会显示一条消息,指出我在访问令牌前面缺少承载者
将承载者添加到标头解决了该问题
Adding security logs to the logback.xml gives me a message that I was missing bearer in front of access token
Adding bearer to the header solve the issue