原文: 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

  1. $ mvn archetype:generate -DgroupId=com.howtodoinjava
  2. -DartifactId=SpringPasswordHashingDemo
  3. -DarchetypeArtifactId=maven-archetype-quickstart
  4. -DinteractiveMode=false

现在,使用以下依赖项更新pom.xml,并运行命令mvn:eclipse:eclipse以支持项目 Eclipse。

pom.xml

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.howtodoinjava</groupId>
  5. <artifactId>SpringPasswordHashingDemo</artifactId>
  6. <packaging>jar</packaging>
  7. <version>1.0-SNAPSHOT</version>
  8. <name>SpringPasswordHashingDemo</name>
  9. <url>http://maven.apache.org</url>
  10. <properties>
  11. <org.springframework.version>3.0.5.RELEASE</org.springframework.version>
  12. </properties>
  13. <dependencies>
  14. <!-- Spring Core -->
  15. <dependency>
  16. <groupId>junit</groupId>
  17. <artifactId>junit</artifactId>
  18. <version>4.4</version>
  19. <scope>test</scope>
  20. </dependency>
  21. <dependency>
  22. <groupId>cglib</groupId>
  23. <artifactId>cglib</artifactId>
  24. <version>2.2</version>
  25. </dependency>
  26. <dependency>
  27. <groupId>org.springframework</groupId>
  28. <artifactId>spring-core</artifactId>
  29. <version>${org.springframework.version}</version>
  30. </dependency>
  31. <dependency>
  32. <groupId>org.springframework</groupId>
  33. <artifactId>spring-expression</artifactId>
  34. <version>${org.springframework.version}</version>
  35. </dependency>
  36. <dependency>
  37. <groupId>org.springframework</groupId>
  38. <artifactId>spring-beans</artifactId>
  39. <version>${org.springframework.version}</version>
  40. </dependency>
  41. <dependency>
  42. <groupId>org.springframework</groupId>
  43. <artifactId>spring-context</artifactId>
  44. <version>${org.springframework.version}</version>
  45. </dependency>
  46. <dependency>
  47. <groupId>org.springframework</groupId>
  48. <artifactId>spring-context-support</artifactId>
  49. <version>${org.springframework.version}</version>
  50. </dependency>
  51. <dependency>
  52. <groupId>org.springframework</groupId>
  53. <artifactId>spring-test</artifactId>
  54. <version>${org.springframework.version}</version>
  55. <scope>test</scope>
  56. </dependency>
  57. <!-- Spring Security -->
  58. <dependency>
  59. <groupId>org.springframework.security</groupId>
  60. <artifactId>spring-security-core</artifactId>
  61. <version>${org.springframework.version}</version>
  62. <type>jar</type>
  63. <scope>compile</scope>
  64. </dependency>
  65. <dependency>
  66. <groupId>org.springframework.security</groupId>
  67. <artifactId>spring-security-web</artifactId>
  68. <version>${org.springframework.version}</version>
  69. <type>jar</type>
  70. <scope>compile</scope>
  71. </dependency>
  72. <dependency>
  73. <groupId>org.springframework.security</groupId>
  74. <artifactId>spring-security-config</artifactId>
  75. <version>${org.springframework.version}</version>
  76. <type>jar</type>
  77. <scope>compile</scope>
  78. </dependency>
  79. <dependency>
  80. <groupId>org.springframework.security</groupId>
  81. <artifactId>spring-security-taglibs</artifactId>
  82. <version>${org.springframework.version}</version>
  83. <type>jar</type>
  84. <scope>compile</scope>
  85. </dependency>
  86. </dependencies>
  87. </project>

步骤 2)创建安全配置文件

我创建了application-security.xml文件,并将安全配置放入其中。

application-security.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans:beans xmlns="http://www.springframework.org/schema/security"
  3. xmlns:beans="http://www.springframework.org/schema/beans"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  7. http://www.springframework.org/schema/security
  8. http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
  9. <global-method-security secured-annotations="enabled" />
  10. <authentication-manager alias="authenticationManager">
  11. <authentication-provider>
  12. <user-service>
  13. <user name="lokesh" password="password1" authorities="ROLE_USER" />
  14. <user name="admin" password="password2" authorities="ROLE_ADMIN" />
  15. </user-service>
  16. </authentication-provider>
  17. </authentication-manager>
  18. <beans:bean id="demoService" class="com.howtodoinjava.DemoService"/>
  19. </beans:beans>

步骤 3)建立受保护的方法

DemoService.java

  1. package com.howtodoinjava;
  2. import org.springframework.security.access.annotation.Secured;
  3. public class DemoService
  4. {
  5. @Secured("ROLE_USER")
  6. public void method()
  7. {
  8. System.out.println("Method called");
  9. }
  10. }

步骤 4)使用 JUnit 测试身份验证

在 junit 测试中,我们将以编程方式配置 spring 上下文,然后将通过默认用户详细信息服务中的用户名访问用户。 在极端情况下,它是内存中实现,在您的情况下,它可能与某些基于 jdbc 的用户详细信息服务或某些其他自定义用户详细信息服务不同。 因此,请相应地修改查找。

我们将测试各种方案,例如有效用户,无效用户,无效角色等。您可以根据选择添加/删除方案。

TestDemoService.java

  1. package com.howtodoinjava;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import org.junit.BeforeClass;
  5. import org.junit.Test;
  6. import org.springframework.context.ApplicationContext;
  7. import org.springframework.context.support.ClassPathXmlApplicationContext;
  8. import org.springframework.security.access.AccessDeniedException;
  9. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  10. import org.springframework.security.core.Authentication;
  11. import org.springframework.security.core.GrantedAuthority;
  12. import org.springframework.security.core.authority.GrantedAuthorityImpl;
  13. import org.springframework.security.core.context.SecurityContextHolder;
  14. import org.springframework.security.core.userdetails.UserDetails;
  15. import org.springframework.security.core.userdetails.memory.InMemoryDaoImpl;
  16. public class TestDemoService {
  17. static ApplicationContext applicationContext = null;
  18. static InMemoryDaoImpl userDetailsService = null;
  19. /**
  20. * Initialize the application context to re-use in all test cases
  21. * */
  22. @BeforeClass
  23. public static void setup()
  24. {
  25. //Create application context instance
  26. applicationContext = new ClassPathXmlApplicationContext("application-security.xml");
  27. //Get user details service configured in configuration
  28. userDetailsService = applicationContext.getBean(InMemoryDaoImpl.class);
  29. }
  30. /**
  31. * Test the valid user with valid role
  32. * */
  33. @Test
  34. public void testValidRole()
  35. {
  36. //Get the user by username from configured user details service
  37. UserDetails userDetails = userDetailsService.loadUserByUsername ("lokesh");
  38. Authentication authToken = new UsernamePasswordAuthenticationToken (userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities());
  39. SecurityContextHolder.getContext().setAuthentication(authToken);
  40. DemoService service = (DemoService) applicationContext.getBean("demoService");
  41. service.method();
  42. }
  43. /**
  44. * Test the valid user with INVALID role
  45. * */
  46. @Test (expected = AccessDeniedException.class)
  47. public void testInvalidRole()
  48. {
  49. UserDetails userDetails = userDetailsService.loadUserByUsername ("lokesh");
  50. List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
  51. authorities.add(new GrantedAuthorityImpl("ROLE_INVALID"));
  52. Authentication authToken = new UsernamePasswordAuthenticationToken (userDetails.getUsername(), userDetails.getPassword(), authorities);
  53. SecurityContextHolder.getContext().setAuthentication(authToken);
  54. DemoService service = (DemoService) applicationContext.getBean("demoService");
  55. service.method();
  56. }
  57. /**
  58. * Test the INVALID user
  59. * */
  60. @Test (expected = AccessDeniedException.class)
  61. public void testInvalidUser()
  62. {
  63. UserDetails userDetails = userDetailsService.loadUserByUsername ("admin");
  64. List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
  65. authorities.add(new GrantedAuthorityImpl("ROLE_INVALID"));
  66. Authentication authToken = new UsernamePasswordAuthenticationToken (userDetails.getUsername(), userDetails.getPassword(), authorities);
  67. SecurityContextHolder.getContext().setAuthentication(authToken);
  68. DemoService service = (DemoService) applicationContext.getBean("demoService");
  69. service.method();
  70. }
  71. }

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

学习快乐!

源码下载