原文: 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/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
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
* */
@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();
}
}
如您所见,所有测试用例均按预期通过。
学习快乐!