第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

單元測(cè)試

1. 前言

上節(jié)我們介紹了 Spring Security 安全框架中的加解密功能,本節(jié)我們討論 Spring Security 項(xiàng)目單元測(cè)試的實(shí)現(xiàn)。

在程序開(kāi)發(fā)過(guò)程中,單元測(cè)試環(huán)境往往貫穿始終。

本節(jié)我們主要討論如何通過(guò)單元測(cè)試保障 Spring Security 應(yīng)用的健壯性。

2. 方法安全測(cè)試

圖片描述

2.1 場(chǎng)景:構(gòu)造 MessageService 接口,要求認(rèn)證過(guò)得用戶(hù)才能訪(fǎng)問(wèn)它。

public class HelloMessageService implements MessageService {
    @PreAuthorize("authenticated")
    public String getMessage() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return "Hello " + authentication;
    }
}

認(rèn)證過(guò)的用戶(hù)調(diào)用 getMessage 方法時(shí),會(huì)得到如下返回:

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

2.1.1 建立 Spring Security 單元測(cè)試

在使用 Spring Security 單元測(cè)試之前,首先需要做一些初始化,如下:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration 
public class WithMockUserTests {
  • @RunWith 注解用于創(chuàng)建 ApplicationContext 對(duì)象,這里和其他的 Spring 應(yīng)用單元測(cè)試一樣,此處不再贅述。

  • @ContextConfiguration 注解用于上下文相關(guān)的配置選項(xiàng),此處使用默認(rèn)值即可,同樣,這也是 Spring 單元測(cè)試所涉及的內(nèi)容,此處不做贅述。

我們構(gòu)造的 getMessage 方法是需要認(rèn)證用戶(hù)才能訪(fǎng)問(wèn)的,如果是非認(rèn)證用戶(hù)訪(fǎng)問(wèn),則應(yīng)該拋出相應(yīng)異常。

針對(duì)這種場(chǎng)景建立以下單元測(cè)試方法:

@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void getMessageUnauthenticated() {
    messageService.getMessage();
}

2.1.2 @WithMockUser

接下來(lái)我們要?jiǎng)?chuàng)造認(rèn)證用戶(hù),是用的方法是增加 @WithMockUser 注解,該注解會(huì)構(gòu)造一個(gè)用戶(hù)名為「user」,密碼為「password」,角色為「ROLE_USER」的用戶(hù):

@Test
@WithMockUser
public void getMessageWithMockUser() {
	String message = messageService.getMessage();
}

指定用戶(hù)的用戶(hù)名:

@Test
@WithMockUser("customUsername")
public void getMessageWithMockUserCustomUsername() {
    String message = messageService.getMessage();
}

指定用戶(hù)的角色:

@Test
@WithMockUser(username="admin",roles={"USER","ADMIN"})
public void getMessageWithMockUserCustomUser() {
    String message = messageService.getMessage();
    ...
}

不指定用戶(hù)的角色,直接定義用戶(hù)的權(quán)限:

@Test
@WithMockUser(username = "admin", authorities = { "ADMIN", "USER" })
public void getMessageWithMockUserCustomAuthorities() {
    String message = messageService.getMessage();
    ...
}

冒煙測(cè)試用的用戶(hù)可以定義在方法前,也可以定義在類(lèi)聲明前,使整個(gè)類(lèi)范圍內(nèi)都使用相同用戶(hù):

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WithMockUser(username="admin",roles={"USER","ADMIN"})
public class WithMockUserTests {
}

2.1.3 @WithAnonymousUser

如果需要測(cè)試匿名用戶(hù),可通過(guò) @WithAnonymousUser 注解實(shí)現(xiàn):

@RunWith(SpringJUnit4ClassRunner.class)
@WithMockUser
public class WithUserClassLevelAuthenticationTests {

    @Test
    public void withMockUser1() {
    }

    @Test
    public void withMockUser2() {
    }

    @Test
    @WithAnonymousUser
    public void anonymous() throws Exception {
      // 使用匿名用戶(hù)訪(fǎng)問(wèn)該方法
    }
}

2.1.4 @WithUserDetails

當(dāng) @WithMockUser 不適用時(shí),比如我們需要認(rèn)證主體是一些特殊類(lèi)型,這時(shí)就需要自定義 UserDetails,假設(shè)我們已經(jīng)有了一個(gè) UserDetailsService 的 bean 聲明:

@Test
@WithUserDetails
public void getMessageWithUserDetails() {
    String message = messageService.getMessage();
    ...
}

我們也可以指定用戶(hù)名,用來(lái)在 UserDetailsService 中返回指定用戶(hù):

@Test
@WithUserDetails("customUsername")
public void getMessageWithUserDetailsCustomUsername() {
    String message = messageService.getMessage();
    ...
}

我們還可以指定 UserDetailsService 的實(shí)現(xiàn) bean:

@Test
@WithUserDetails(value="customUsername", userDetailsServiceBeanName="myUserDetailsService")
public void getMessageWithUserDetailsServiceBeanName() {
    String message = messageService.getMessage();
    ...
}

2.1.5 @WithSecurityContext

當(dāng)我們不希望建立 Authentication 對(duì)象,而希望直接使用 SecurityContext 時(shí),可用如下方法:

@Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class)
public @interface WithMockCustomUser {

    String username() default "rob";

    String name() default "Rob Winch";
}

3. Spring MVC 測(cè)試集成

這部分需要配合 Spring MVC 的集成測(cè)試模塊。

3.1 建立 Spring MVC 單元測(cè)試

import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SecurityConfig.class)
@WebAppConfiguration
public class CsrfShowcaseTests {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mvc;

    @Before
    public void setup() {
        mvc = MockMvcBuilders
                .webAppContextSetup(context)
                .apply(springSecurity()) 
                .build();
    }

...

3.2 測(cè)試 CSRF

為請(qǐng)求增加有效的 CSRF Token:

mvc.perform(post("/").with(csrf()))

把 CSRF Token 增加到請(qǐng)求頭中:

mvc.perform(post("/").with(csrf().asHeader()))

增加一個(gè)不合法的 CSRF Token:

mvc.perform(post("/").with(csrf().useInvalidToken()))

配置請(qǐng)求攜帶默認(rèn)用戶(hù)信息:

mvc.perform(get("/").with(user("user")))

配置請(qǐng)求攜帶自定義用戶(hù)信息

mvc.perform(get("/admin").with(user("admin").password("pass").roles("USER","ADMIN")))

使用自定義的 userDetails 實(shí)例:

mvc.perform(get("/").with(user(userDetails)))

使用匿名用戶(hù):

mvc.perform(get("/").with(anonymous()))

使用自定義身份信息:

mvc.perform(get("/").with(authentication(authentication)))

使用自定義安全上下文:

mvc.perform(get("/").with(securityContext(securityContext)))

將用戶(hù)信息應(yīng)用到所有請(qǐng)求中:

mvc = MockMvcBuilders
        .webAppContextSetup(context)
        .defaultRequest(get("/").with(user("user").roles("ADMIN")))
        .apply(springSecurity())
        .build();

我們還可以使用注解方式配置用戶(hù)信息:

@Test
@WithMockUser(roles="ADMIN")
public void requestProtectedUrlWithUser() throws Exception {
mvc
        .perform(get("/"))
        ...
}

3.3 測(cè)試 HTTP 基礎(chǔ)認(rèn)證

使用 httpBasic 測(cè)試基本認(rèn)證:

mvc.perform(get("/").with(httpBasic("user","password")))

這一步相當(dāng)于為請(qǐng)求增加了以下認(rèn)證頭:

Authorization: Basic dXNlcjpwYXNzd29yZA==

4. 小結(jié)

本節(jié)介紹了 Spring Security 項(xiàng)目實(shí)現(xiàn)單元測(cè)試的方法,主要內(nèi)容有:

  • Spring Security 的單元測(cè)試是基于 Spring 單元測(cè)試擴(kuò)展;
  • Spring Security 的單元測(cè)試核心思想是模擬出認(rèn)證用戶(hù)及相關(guān)用戶(hù)信息;
  • Spring MVC 環(huán)境下的單元測(cè)試可以模擬各種安全頭信息及用戶(hù)認(rèn)證信息。

至此,關(guān)于 Spring Security 的內(nèi)容就全部結(jié)束了。