原文: 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()方法即可随时访问 spring 上下文。
该上下文具有实际主体或用户的引用,我们必须对其访问权限进行验证。
Spring Security 单元测试
我正在创建一个简单的 Maven 项目,并且将编写最少的代码,以便我可以专注于仅测试此帖子范围内的内容,即身份验证。 然后,我将用一个需要“ ROLE_USER”的单一方法编写一个演示服务类。 如果尝试访问此方法而没有“ ROLE_USER”,则将获得预期的AccessDeniedException。 很简单,不是吗?
步骤 1)创建项目
让我们使用以下命令创建 Java 项目:
Console
$ mvn archetype:generate -DgroupId=com.howtodoinjava-DartifactId=SpringPasswordHashingDemo-DarchetypeArtifactId=maven-archetype-quickstart-DinteractiveMode=false
现在,使用以下依赖项更新pom.xml,并运行命令mvn:eclipse:eclipse以支持项目 Eclipse。
pom.xml
<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
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/securityhttp://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
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 的用户详细信息服务或某些其他自定义用户详细信息服务不同。 因此,请相应地修改查找。
我们将测试各种方案,例如有效用户,无效用户,无效角色等。您可以根据选择添加/删除方案。
TestDemoService.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* */@BeforeClasspublic static void setup(){//Create application context instanceapplicationContext = new ClassPathXmlApplicationContext("application-security.xml");//Get user details service configured in configurationuserDetailsService = applicationContext.getBean(InMemoryDaoImpl.class);}/*** Test the valid user with valid role* */@Testpublic void testValidRole(){//Get the user by username from configured user details serviceUserDetails 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();}}
如您所见,所有测试用例均按预期通过。
学习快乐!
