Package sagan.support

Source Code of sagan.support.SecurityRequestPostProcessors$CsrfRequestPostProcessor

package sagan.support;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.context.HttpRequestResponseHolder;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.test.web.servlet.request.RequestPostProcessor;
import org.springframework.util.Assert;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

/**
* Demonstrates how to use a {@link RequestPostProcessor} to add request-building methods
* for establishing a security context for Spring Security. While these are just examples,
* <a href="https://jira.springsource.org/browse/SEC-2015">official support</a> for Spring
* Security is planned.
*/
public final class SecurityRequestPostProcessors {

    public static CsrfRequestPostProcessor csrf() {
        return new CsrfRequestPostProcessor();
    }

    /**
     * Establish a security context for a user with the specified username. All details
     * are declarative and do not require that the user actually exists. This means that
     * the authorities or roles need to be specified too.
     */
    public static UserRequestPostProcessor user(Object username) {
        return new UserRequestPostProcessor(username);
    }

    /**
     * Establish a security context for a user with the specified username. The additional
     * details are obtained from the {@link UserDetailsService} declared in the
     * {@link WebApplicationContext}.
     */
    public static UserDetailsRequestPostProcessor userDeatilsService(String username) {
        return new UserDetailsRequestPostProcessor(username);
    }

    /**
     * Establish a security context with the given {@link SecurityContext} and thus be
     * authenticated with {@link SecurityContext#getAuthentication()}.
     */
    public SecurityContextRequestPostProcessor securityContext(SecurityContext securityContext) {
        return new SecurityContextRequestPostProcessor(securityContext);
    }

    private static class CsrfRequestPostProcessor implements RequestPostProcessor {

        private CsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();

        /*
         * (non-Javadoc)
         * @see
         * org.springframework.test.web.servlet.request.RequestPostProcessor
         * #postProcessRequest(org.springframework.mock.web.MockHttpServletRequest)
         */
        @Override
        public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
            CsrfToken token = repository.generateToken(request);
            repository.saveToken(token, request, new MockHttpServletResponse());
            request.setParameter(token.getParameterName(), token.getToken());
            return request;
        }
    }

    /**
     * Support class for {@link RequestPostProcessor}'s that establish a Spring Security
     * context
     */
    private static abstract class SecurityContextRequestPostProcessorSupport {

        private SecurityContextRepository repository = new HttpSessionSecurityContextRepository();

        final void save(Authentication authentication, HttpServletRequest request) {
            SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
            securityContext.setAuthentication(authentication);
            save(securityContext, request);
        }

        final void save(SecurityContext securityContext, HttpServletRequest request) {
            HttpServletResponse response = new MockHttpServletResponse();

            HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response);
            repository.loadContext(requestResponseHolder);

            request = requestResponseHolder.getRequest();
            response = requestResponseHolder.getResponse();

            repository.saveContext(securityContext, request, response);
        }
    }

    public final static class SecurityContextRequestPostProcessor
            extends SecurityContextRequestPostProcessorSupport implements RequestPostProcessor {

        private final SecurityContext securityContext;

        private SecurityContextRequestPostProcessor(SecurityContext securityContext) {
            this.securityContext = securityContext;
        }

        public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
            save(securityContext, request);
            return request;
        }
    }

    public final static class UserRequestPostProcessor
            extends SecurityContextRequestPostProcessorSupport implements RequestPostProcessor {

        private final Object username;

        private String rolePrefix = "ROLE_";

        private Object credentials;

        private List<GrantedAuthority> authorities = new ArrayList<>();

        private UserRequestPostProcessor(Object username) {
            Assert.notNull(username, "username cannot be null");
            this.username = username;
        }

        /**
         * Sets the prefix to append to each role if the role does not already start with
         * the prefix. If no prefix is desired, an empty String or null can be used.
         */
        public UserRequestPostProcessor rolePrefix(String rolePrefix) {
            this.rolePrefix = rolePrefix;
            return this;
        }

        /**
         * Specify the roles of the user to authenticate as. This method is similar to
         * {@link #authorities(GrantedAuthority...)}, but just not as flexible.
         *
         * @param roles The roles to populate. Note that if the role does not start with
         *        {@link #rolePrefix(String)} it will automatically be prepended. This
         *        means by default {@code roles("ROLE_USER")} and {@code roles("USER")}
         *        are equivalent.
         * @see #authorities(GrantedAuthority...)
         * @see #rolePrefix(String)
         */
        public UserRequestPostProcessor roles(String... roles) {
            List<GrantedAuthority> authorities = new ArrayList<>(roles.length);
            for (String role : roles) {
                if (rolePrefix == null || role.startsWith(rolePrefix)) {
                    authorities.add(new SimpleGrantedAuthority(role));
                } else {
                    authorities.add(new SimpleGrantedAuthority(rolePrefix + role));
                }
            }
            return this;
        }

        /**
         * Populates the user's {@link GrantedAuthority}'s.
         *
         * @param authorities
         * @see #roles(String...)
         */
        public UserRequestPostProcessor authorities(GrantedAuthority... authorities) {
            this.authorities = Arrays.asList(authorities);
            return this;
        }

        public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(username, credentials, authorities);
            save(authentication, request);
            return request;
        }
    }

    public final static class UserDetailsRequestPostProcessor
            extends SecurityContextRequestPostProcessorSupport implements RequestPostProcessor {

        private final String username;

        private String userDetailsServiceBeanId;

        private UserDetailsRequestPostProcessor(String username) {
            this.username = username;
        }

        /**
         * Use this method to specify the bean id of the {@link UserDetailsService} to use
         * to look up the {@link UserDetails}.
         *
         * <p>
         * By default a lookup of {@link UserDetailsService} is performed by type. This
         * can be problematic if multiple {@link UserDetailsService} beans are declared.
         */
        public UserDetailsRequestPostProcessor userDetailsServiceBeanId(String userDetailsServiceBeanId) {
            this.userDetailsServiceBeanId = userDetailsServiceBeanId;
            return this;
        }

        public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
            UsernamePasswordAuthenticationToken authentication = authentication(request.getServletContext());
            save(authentication, request);
            return request;
        }

        private UsernamePasswordAuthenticationToken authentication(ServletContext servletContext) {
            ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
            UserDetailsService userDetailsService = userDetailsService(context);
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            return new UsernamePasswordAuthenticationToken(
                    userDetails, userDetails.getPassword(), userDetails.getAuthorities());
        }

        private UserDetailsService userDetailsService(ApplicationContext context) {
            if (userDetailsServiceBeanId == null) {
                return context.getBean(UserDetailsService.class);
            }
            return context.getBean(userDetailsServiceBeanId, UserDetailsService.class);
        }
    }

    private SecurityRequestPostProcessors() {
    }

}
TOP

Related Classes of sagan.support.SecurityRequestPostProcessors$CsrfRequestPostProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.