• 11. Testing Method Security(测试方法安全性)


    本节演示如何使用Spring安全性的测试支持来测试基于方法的安全性。我们首先介绍一个MessageService,它要求用户通过身份验证才能访问它。

    public class HelloMessageService implements MessageService {

            @PreAuthorize("authenticated")

            public String getMessage() {

                    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

                    return "Hello " + authentication;

            }

    }

    getMessage的结果是一个字符串,对当前的Spring安全认证说“你好”。输出示例如下所示。

    Hello

    org.springframework.security.authentication.UsernamePasswordAuthenticationToken@ca25360: 

    Principal: org.springframework.security.core.userdetails.User@36ebcb:

     Username: user;

     Password: [PROTECTED]; 

    Enabled: true; AccountNonExpired: true; 

    credentialsNonExpired: true; 

    AccountNonLocked: true; 

    Granted Authorities: ROLE_USER; 

    Credentials: [PROTECTED]; 

    Authenticated: true;

     Details: null;

     Granted Authorities: ROLE_USER

    11.1 Security Test Setup(安全测试设置)

    在使用Spring安全测试支持之前,我们必须执行一些设置。下面是一个例子:
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration
    public class WithMockUserTests {

    这是如何设置spring安全测试的一个基本示例。亮点是:

    @RunWith指示spring-test模块应该创建一个应用上下文。这与使用现有的spring-test支持没有什么不同。有关更多信息,请参考 [Spring Reference](https://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#integration-testing-annotations-standard)

    @ContextConfiguration指示spring-test用于创建应用程序上下文的配置。由于未指定配置,将尝试默认配置位置。这与使用现有的spring-test支持没有什么不同。有关更多信息,请参考 [Spring Reference](https://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#integration-testing-annotations-standard)

    Spring安全性使用WithSecurityContextTestExecutionListener连接到Spring Test支持,这将确保我们的Spring Test由正确的用户运行。它通过在运行测试之前填充SecurityContextHolder来实现这一点。测试完成后,它将清除SecurityContextHolder.如果您只需要Spring安全相关的支持,您可以用@ SecurityTestExecutionListeners替换@ContextConfiguration。

    请记住,我们在我们的HelloMessageService中添加了@PreAuthorize注释,因此它需要一个经过身份验证的用户来调用它。
    如果我们运行下面的测试,我们希望下面的测试能够通过:
    @Test(expected = AuthenticationCredentialsNotFoundException.class)
    public void getMessageUnauthenticated() {
    messageService.getMessage();
    }

    11.2 @WithMockUser(使用模拟用户)

    11.3 @WithAnonymousUser(使用匿名用户)

    使用@ WithAnonymousUser允许以匿名用户身份运行。当您希望用特定用户运行大多数测试,但希望以匿名用户身份运行一小部分测试时,这一点尤其方便。

    例如,以下将使用@WithMockUser和匿名用户作为匿名用户与MockUser1和MockUser2一起运行。


     

    11.4 @WithUserDetails(用户详细信息)

    虽然@WithMockUser是一种非常方便的入门方式,但它可能并不适用所有情况。例如,应用程序通常希望身份验证主体是特定类型的。这样做是为了使应用程序可以将主体作为自定义类型引用,并减少Spring Security上的耦合。

    自定义主体通常由自定义用户详细信息服务返回,该服务返回实现用户详细信息和自定义类型的对象。对于这种情况,使用自定义的用户详细信息服务创建测试用户是很有用的。这正是@WithUserDetails所做的。

    假设我们有一个作为bean公开的UserDetailservice,下面的测试将使用类型为UserNamePasswordAuthenticationToken的身份验证和从UserDetailservice返回的用户名为“user”的主体来调用。


     

    我们还可以定制用于从我们的UserDetailsService中查找用户的用户名。例如,该测试将使用用户名为“自定义用户名”的UserDetailsService 返回的主体来执行。


     

    我们还可以提供一个显式的bean名称来查找UserDetailsService。例如,该测试将使用用户名为“myUserDetailsService”的bean来查找用户名“customUsername”。


     

    像@WithMockUser一样,我们也可以在类级别放置我们的注释,以便每个测试使用相同的用户。但是与@WithMockUser不同的是,@WithUserDetails要求用户存在。

    11.5 @WithSecurityContext(使用安全上下文)

    我们已经看到,如果我们不使用自定义身份验证主体,那么@WithMockUser是一个很好的选择。接下来,我们发现@WithUserDetails将允许我们使用自定义的UserDetailsService来创建我们的身份验证主体,但要求用户存在。我们现在将看到一个允许最大灵活性的选项。

    我们可以创建自己的注释,使用@WithSecurityContext来创建我们想要的任何SecurityContext(安全上下文)。例如,我们可以创建一个名为@WithMockCustomUser的注释,如下所示:


     

    您可以看到@WithMockCustomUser用@WithSecurityContext注释进行了注释。这是向Spring安全测试支持发出的信号,表明我们打算为测试创建一个安全上下文。@WithSecurityContext注释要求我们指定一个安全上下文工厂,该工厂将根据我们的@ WithMockCustomUser注释创建一个新的安全上下文。您可以在下面找到我们的WithMockCustomUserSecurityContextFactory实现:


     

    我们现在可以用新的注释来注释测试类或测试方法,而Spring Security的WithSecurityContextTestExecutionListener将确保我们的SecurityContext被适当地填充。

    当使用安全上下文工厂实现创建您自己的实现时,很高兴知道它们可以用标准的Spring注释进行注释。例如,WithUserDetailsSecurityContextFactory使用@Autowired注释来获取用户详细信息服务:


     

    11.6 Test Meta Annotations(测试元注释)

    如果您经常在测试中重用同一个用户,那么重复指定属性是不理想的。例如,如果有许多与用户名为“admin”且角色为ROLE_USER和ROLE_ADMIN的管理用户相关的测试,您必须编写:

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

    我们可以使用元注释,而不是到处重复。例如,我们可以创建一个名为WithMockAdmin的元注释:

    @Retention(RetentionPolicy.RUNTIME)

    @WithMockUser(value="rob",roles="ADMIN")

    public@interfaceWithMockAdmin { }

    现在我们可以像使用更详细的@WithMockUser一样使用@WithMockAdmin。

    元注释与上面描述的任何测试注释一起工作。例如,这意味着我们也可以为@ WithUserDetails(“admin”)创建一个元注释。

  • 相关阅读:
    信息安全系统设计基础第八周期中复习总结
    layui下各种富文本的冲突情况
    TP3.2+find_set_in 以及 find_set_in和like的区别
    tp5+linux+apache php7.1.30环境下,上传图片报错:mkdir():permission denied
    一次基于老古董thinkPHP3.1的修改尝试
    微信网页开发 thinkphp5.0的try-catch和重定向
    CentOS 7.2下服务器配置(linux+apache+php+mysql)
    微信小程序踩坑(不定时更新)
    PHP 定时自动执行代码
    PHP TP5 文章评论+积分+签到
  • 原文地址:https://www.cnblogs.com/jrkl/p/13513219.html
Copyright © 2020-2023  润新知