Spring Security: Integrate In-Memory Authentication for Test Automation

Use Case
To automate test of our web services apis, we need add test users in test environments.

The Solution
We configure Spring Security AuthenticationManager: first add  in-memory DaoAuthenticationProvider in test environments then add other authentication providers.

The legacy code uses xml to configure authenticationManager and intercept-url rules, so I create org.springframework.security.authenticationManager bean. If you are using pure java config, please check Spring Security Java Config.
@Configuration
public class WebSecurityConfiguration {
    private static final String[] ENV_SUPPORT_TEST_USER = {PROFILE_LOCAL, PROFILE_XX};

    @Autowired
    private Environment environment;

    @Bean(name = "org.springframework.security.authenticationManager")
    public AuthenticationManager authenticationManager() {
        final List providers = new ArrayList<>();

        final String env = System.getProperty("env");
        if (StringUtils.isBlank(env)) {
            throw new BusinessException(ErrorCode.INTERNAL_ERROR, "env is empty");
        }
        // The order matters: don't change the order - it will first try to use the test user
        // if not succeed then use ldap
        // add test user for local, q1, e1 only
        if (ArrayUtils.contains(ENV_SUPPORT_TEST_USER, env)) {
            addTestUserAuthProvider(providers);
        }

        if (PROFILE_LOCAL.equals(env) || PROFILE_DOCKER.equals(env)) {
            addLdapProviderForLocal(providers);
        } else {
            // application is deployed to aws, use different LdapAuthenticationProvider
            addLdapProviderForAwsEnv(providers);
        }

        final AuthenticationManager authenticationManager = new ProviderManager(providers);
        return authenticationManager;
    }

    protected void addTestUserAuthProvider(final List providers) {
        final DaoAuthenticationProvider testUserAuthProvider = new DaoAuthenticationProvider();
        final Collection users = new ArrayList<>();
        // add admin user
        UserDetails user = new User(environment.getProperty("spring.security.test.user.adminOnly.name"),
                environment.getProperty("spring.security.test.user.adminOnly.password"),
                Lists.newArrayList(new SimpleGrantedAuthority(environment.getProperty("spring.security.adminGroup"))));
        users.add(user);
        // add provisioner
        user = new User(environment.getProperty("spring.security.test.user.provisionerOnly.name"),
                environment.getProperty("spring.security.test.user.provisionerOnly.password"), Lists.newArrayList(
                        new SimpleGrantedAuthority(environment.getProperty("spring.security.provisionGroup"))));
        users.add(user);

        // add user with admin and provisioner
        user = new User(environment.getProperty("spring.security.test.user.adminProvisioner.name"),
                environment.getProperty("spring.security.test.user.adminProvisioner.password"),
                Lists.newArrayList(new SimpleGrantedAuthority(environment.getProperty("spring.security.adminGroup")),
                        new SimpleGrantedAuthority(environment.getProperty("spring.security.provisionGroup"))));
        users.add(user);

        final UserDetailsService userDetailsService = new InMemoryUserDetailsManager(users);
        testUserAuthProvider.setUserDetailsService(userDetailsService);

        providers.add(testUserAuthProvider);
    }
}

Testing with Rest-Assured
Now we can use Rest-Assured to login and capture the session and reuse it in subsequent requests.
RestAssured.reset();
RestAssured.baseURI = baseURI;
RestAssured.basePath = basePath;
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
RestAssured.config = config().logConfig(new LogConfig());
RestAssured.useRelaxedHTTPSValidation();

final SessionFilter sessionFilter = new SessionFilter();
given().auth()
.form(user, passwd,
        new FormAuthConfig("/j_spring_security_check", "j_username", "j_password"))
.filter(sessionFilter).expect().statusCode(200).when().get("/api");

// later...
given().filter(sessionFilter).contentType(ContentType.JSON).when().delete(productUrl).then()
        .statusCode(200);

Post a Comment

Labels

Java (159) Lucene-Solr (112) Interview (61) All (58) J2SE (53) Algorithm (45) Soft Skills (38) Eclipse (33) Code Example (31) Linux (25) JavaScript (23) Spring (22) Windows (22) Web Development (20) Tools (19) Nutch2 (18) Bugs (17) Debug (16) Defects (14) Text Mining (14) J2EE (13) Network (13) Troubleshooting (13) PowerShell (11) Chrome (9) Design (9) How to (9) Learning code (9) Performance (9) Problem Solving (9) UIMA (9) html (9) Http Client (8) Maven (8) Security (8) bat (8) blogger (8) Big Data (7) Continuous Integration (7) Google (7) Guava (7) JSON (7) Shell (7) ANT (6) Coding Skills (6) Database (6) Lesson Learned (6) Programmer Skills (6) Scala (6) Tips (6) css (6) Algorithm Series (5) Cache (5) Dynamic Languages (5) IDE (5) System Design (5) adsense (5) xml (5) AIX (4) Code Quality (4) GAE (4) Git (4) Good Programming Practices (4) Jackson (4) Memory Usage (4) Miscs (4) OpenNLP (4) Project Managment (4) Spark (4) Testing (4) ads (4) regular-expression (4) Android (3) Apache Spark (3) Become a Better You (3) Concurrency (3) Eclipse RCP (3) English (3) Happy Hacking (3) IBM (3) J2SE Knowledge Series (3) JAX-RS (3) Jetty (3) Restful Web Service (3) Script (3) regex (3) seo (3) .Net (2) Android Studio (2) Apache (2) Apache Procrun (2) Architecture (2) Batch (2) Bit Operation (2) Build (2) Building Scalable Web Sites (2) C# (2) C/C++ (2) CSV (2) Career (2) Cassandra (2) Distributed (2) Fiddler (2) Firefox (2) Google Drive (2) Gson (2) How to Interview (2) Html Parser (2) Http (2) Image Tools (2) JQuery (2) Jersey (2) LDAP (2) Life (2) Logging (2) Python (2) Software Issues (2) Storage (2) Text Search (2) xml parser (2) AOP (1) Application Design (1) AspectJ (1) Chrome DevTools (1) Cloud (1) Codility (1) Data Mining (1) Data Structure (1) ExceptionUtils (1) Exif (1) Feature Request (1) FindBugs (1) Greasemonkey (1) HTML5 (1) Httpd (1) I18N (1) IBM Java Thread Dump Analyzer (1) JDK Source Code (1) JDK8 (1) JMX (1) Lazy Developer (1) Mac (1) Machine Learning (1) Mobile (1) My Plan for 2010 (1) Netbeans (1) Notes (1) Operating System (1) Perl (1) Problems (1) Product Architecture (1) Programming Life (1) Quality (1) Redhat (1) Redis (1) Review (1) RxJava (1) Solutions logs (1) Team Management (1) Thread Dump Analyzer (1) Visualization (1) boilerpipe (1) htm (1) ongoing (1) procrun (1) rss (1)

Popular Posts