使用 JUnit 测试 Spring Security Auth

使用 JUnit 测试 Spring Security Auth

原文: 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();
	}

}

如您所见,所有测试用例均按预期通过。

学习快乐!

源码下载