💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 使用 JUnit 测试 Spring Security Auth > 原文: [https://howtodoinjava.com/junit/how-to-unit-test-spring-security-authentication-with-junit/](https://howtodoinjava.com/junit/how-to-unit-test-spring-security-authentication-with-junit/) 学习使用`InMemoryDaoImpl`使用 JUnit 测试用例测试 Spring Security认证。 还学习以编程方式构建完全填充的`authentication`对象,然后在应用程序中使用它。 ## `SecurityContextHolder` Spring Security 基于安全性上下文,本质上是静态的。 从本质上讲,这意味着您无需将其引用注入到 spring 容器中的 bean 或类中。 您只需使用[`SecurityContextHolder.getContext()`](http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/core/context/SecurityContextHolder.html#getContext%28%29)方法即可随时访问 spring 上下文。 该上下文具有实际主体或用户的引用,我们必须对其访问权限进行验证。 ## Spring Security 单元测试 我正在创建一个[简单的 Maven 项目](https://howtodoinjava.com/maven/create-a-simple-java-project-using-maven/),并且将编写最少的代码,以便我可以专注于仅测试此帖子范围内的内容,即身份验证。 然后,我将用一个需要“ `ROLE_USER`”的单一方法编写一个演示服务类。 如果尝试访问此方法而没有“ `ROLE_USER`”,则将获得预期的`AccessDeniedException`。 很简单,不是吗? #### 步骤 1)创建项目 让我们使用以下命令创建 Java 项目: `Console` ```java $ mvn archetype:generate -DgroupId=com.howtodoinjava -DartifactId=SpringPasswordHashingDemo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false ``` 现在,使用以下依赖项更新`pom.xml`,并运行命令`mvn:eclipse:eclipse`以支持项目 Eclipse。 `pom.xml` ```java <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.howtodoinjava</groupId> <artifactId>SpringPasswordHashingDemo</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>SpringPasswordHashingDemo</name> <url>http://maven.apache.org</url> <properties> <org.springframework.version>3.0.5.RELEASE</org.springframework.version> </properties> <dependencies> <!-- Spring Core --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.4</version> <scope>test</scope> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${org.springframework.version}</version> <scope>test</scope> </dependency> <!-- Spring Security --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>${org.springframework.version}</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>${org.springframework.version}</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>${org.springframework.version}</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> <version>${org.springframework.version}</version> <type>jar</type> <scope>compile</scope> </dependency> </dependencies> </project> ``` #### 步骤 2)创建安全配置文件 我创建了`application-security.xml`文件,并将安全配置放入其中。 `application-security.xml` ```java <?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.3.xsd"> <global-method-security secured-annotations="enabled" /> <authentication-manager alias="authenticationManager"> <authentication-provider> <user-service> <user name="lokesh" password="password1" authorities="ROLE_USER" /> <user name="admin" password="password2" authorities="ROLE_ADMIN" /> </user-service> </authentication-provider> </authentication-manager> <beans:bean id="demoService" class="com.howtodoinjava.DemoService"/> </beans:beans> ``` #### 步骤 3)建立受保护的方法 `DemoService.java` ```java package com.howtodoinjava; import org.springframework.security.access.annotation.Secured; public class DemoService { @Secured("ROLE_USER") public void method() { System.out.println("Method called"); } } ``` #### 步骤 4)使用 JUnit 测试身份验证 在 junit 测试中,我们将以编程方式配置 spring 上下文,然后将通过默认用户详细信息服务中的用户名访问用户。 在极端情况下,它是**内存中实现**,在您的情况下,它可能与某些[基于 jdbc 的用户详细信息服务](https://howtodoinjava.com/spring/spring-security/jdbc-user-service-based-spring-security-example/)或某些其他[自定义用户详细信息服务](https://howtodoinjava.com/spring/spring-security/custom-userdetailsservice-example-for-spring-3-security/)不同。 因此,请相应地修改查找。 我们将测试各种方案,例如有效用户,无效用户,无效角色等。您可以根据选择添加/删除方案。 `TestDemoService.java` ```java package com.howtodoinjava; import java.util.ArrayList; import java.util.List; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.GrantedAuthorityImpl; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.memory.InMemoryDaoImpl; public class TestDemoService { static ApplicationContext applicationContext = null; static InMemoryDaoImpl userDetailsService = null; /** * Initialize the application context to re-use in all test cases * */ @BeforeClass public static void setup() { //Create application context instance applicationContext = new ClassPathXmlApplicationContext("application-security.xml"); //Get user details service configured in configuration userDetailsService = applicationContext.getBean(InMemoryDaoImpl.class); } /** * Test the valid user with valid role * */ @Test public void testValidRole() { //Get the user by username from configured user details service UserDetails userDetails = userDetailsService.loadUserByUsername ("lokesh"); Authentication authToken = new UsernamePasswordAuthenticationToken (userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authToken); DemoService service = (DemoService) applicationContext.getBean("demoService"); service.method(); } /** * Test the valid user with INVALID role * */ @Test (expected = AccessDeniedException.class) public void testInvalidRole() { UserDetails userDetails = userDetailsService.loadUserByUsername ("lokesh"); List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); authorities.add(new GrantedAuthorityImpl("ROLE_INVALID")); Authentication authToken = new UsernamePasswordAuthenticationToken (userDetails.getUsername(), userDetails.getPassword(), authorities); SecurityContextHolder.getContext().setAuthentication(authToken); DemoService service = (DemoService) applicationContext.getBean("demoService"); service.method(); } /** * Test the INVALID user * */ @Test (expected = AccessDeniedException.class) public void testInvalidUser() { UserDetails userDetails = userDetailsService.loadUserByUsername ("admin"); List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); authorities.add(new GrantedAuthorityImpl("ROLE_INVALID")); Authentication authToken = new UsernamePasswordAuthenticationToken (userDetails.getUsername(), userDetails.getPassword(), authorities); SecurityContextHolder.getContext().setAuthentication(authToken); DemoService service = (DemoService) applicationContext.getBean("demoService"); service.method(); } } ``` 如您所见,所有测试用例均按预期通过。 学习快乐! [**源码下载**](https://docs.google.com/file/d/0B7yo2HclmjI4akNlUVdXNDJtdDA/edit?usp=sharing)