【问题标题】:@WithMockUser with custom User implementation@WithMockUser 与自定义用户实现
【发布时间】:2019-03-22 13:03:58
【问题描述】:

我正在使用 Spring OAuth2 和 JWT 令牌来保护应用程序。我正在扩展 org.springframework.security.core.userdetails 以便向令牌添加一些额外的属性,然后这些属性可用于执行调用端点的授权。

public class CustomUser extends User {
     private Set<String> bookIds;

     public CustomUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
         super(username, password, authorities);
     }

     public CustomUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
         super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
     }
}

我还有一个 org.springframework.security.access.PermissionEvaluator 的自定义实现,它能够反序列化令牌并检查自定义属性是否是它的一部分,可以将其添加到控制器端点。

@PreAuthorize("hasPermission(authentication, #bookId,'read')")

现在一切正常,我可以通过邮递员测试我的应用程序,并且只有具有有效 JWT 令牌且在其 bookIds 集的 URL 部分具有 bookID 的用户才能访问资源

@PreAuthorize("hasPermission(authentication, #bookId,'read')")
@GetMapping(value = "api/books/{bookId}")
public Book getBook(@PathVariable String bookId) {}

但是,我正在努力对此进行测试,因为这是微服务应用程序的一部分,其中身份验证和服务不是同一个项目的一部分,并且将在不同的虚拟机上运行。理想情况下,我希望能够在每个服务中模拟令牌,并在这个 bookId 集中添加我需要的任何值。 我知道在春季 4 之后我们可以使用@WithMockUser,但是,据我所知,这仅限于用户名/密码/角色/权限,例如:

@WithMockUser(username = "ram", roles={"ADMIN"})

我真正想做的是扩展此注释以支持我的自定义属性“bookId”或在其中注入模拟集的方法。这是否可能,如果没有,我的替代方案是什么,因为我无法在我的单元测试中调用我的身份验证提供程序,因为实现将存在于托管在单独应用程序上的另一个 spring 上下文中。

提前非常感谢!

【问题讨论】:

    标签: java spring unit-testing spring-security spring-security-oauth2


    【解决方案1】:

    您可以使用@WithUserDetails 注释。
    如果您有一个用户名为“user1”的用户,那么您可以使用@WithUserDetails("user1") 注释您的测试,它将使用CustomUser 主体执行,包括与“user1”关联的自定义属性“bookId”。
    您可以在spring-security docs 中找到有关注解的更多信息。

    如果你想要更多的灵活性,你也可以使用@WithSecurityContext注解。
    这允许您创建自己的注释,例如 @WithMockCustomUser,您可以在其中自己设置安全上下文。
    您可以在spring-security docs找到更多详细信息。

    还有一个选项,如果您使用MockMvc 运行测试,则使用request post processor
    你的测试应该是这样的

    mvc
        .perform(get("/api/books/1")
        .with(user(customUser)));
    

    其中customUser 是您在测试中创建的CustomUser 的一个实例。

    【讨论】:

    • with(user(user)) 帮助我向实体添加了其他信息,但现在安全角色被忽略了。我有一条规则,只允许具有特定角色的用户,但即使用户没有角色,该方法也会执行
    猜你喜欢
    • 2016-06-20
    • 1970-01-01
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多