繁体   English   中英

在 Spring 中模拟用户

[英]Mocking a user in Spring

我想编写一个简单的测试,但我的 SecurityConfig 总是让我拒绝访问。 这是我的配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(new TokenAuthenticationFilter(userService), AnonymousAuthenticationFilter.class);
        http.csrf().disable();
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);

        //Options preflight
        http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll();

        //ACL
        http.authorizeRequests().antMatchers(HttpMethod.POST, "/auth/password").hasAnyRole("ADMIN", "CUSTOMER", "REFUGEE");
        http.authorizeRequests().antMatchers("/auth/**").anonymous();

       //Tags
    http.authorizeRequests().antMatchers(HttpMethod.GET, "/tags").hasAnyRole("ADMIN", "CUSTOMER", "REFUGEE");
    http.authorizeRequests().antMatchers(HttpMethod.GET, "/tags/recommendation").hasAnyRole("ADMIN", "CUSTOMER", "REFUGEE");
    http.authorizeRequests().antMatchers(HttpMethod.POST, "/tags").hasAnyRole("ADMIN", "REFUGEE");
    http.authorizeRequests().antMatchers(HttpMethod.GET, "/tags/recommendation/random").hasAnyRole("ADMIN", "CUSTOMER", "REFUGEE");
    http.authorizeRequests().antMatchers(HttpMethod.PUT, "/tags").hasAnyRole("ADMIN");
    http.authorizeRequests().antMatchers(HttpMethod.GET, "/tags/notapproved").hasAnyRole("ADMIN");
    http.authorizeRequests().antMatchers(HttpMethod.PUT, "/tags/approve/{id}").hasAnyRole("ADMIN");
    }

和 AuthenticationFilter:

public class TokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private UserService userService;

    public TokenAuthenticationFilter(UserService userService) {
        super("/");
        this.userService = userService;
    }

    private final String HEADER_SECURITY_TOKEN = "Authorization";
    private final String PARAMETER_SECURITY_TOKEN = "access_token";
    private String token = "";

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        this.token = request.getHeader(HEADER_SECURITY_TOKEN);
        if ("".equals(this.token) || this.token == null) {
            this.token = request.getParameter(PARAMETER_SECURITY_TOKEN);
        }

        //Attempt to authenticate
        Authentication authResult;
        authResult = attemptAuthentication(request, response);
        if (authResult == null) {
             chain.doFilter(request, response);
        } else {
            successfulAuthentication(request, response, chain, authResult);
        }
    }

    /**
     * Attempt to authenticate request - basically just pass over to another
     * method to authenticate request headers
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        Authentication userAuthenticationToken = authUserByToken();
        if (userAuthenticationToken == null) {
            //throw new AuthenticationServiceException(MessageFormat.format("Error | {0}", "Bad Token"));
        }
        return userAuthenticationToken;
    }

    /**
     * authenticate the user based on token, mobile app secret & user agent
     *
     * @return
     */
    private Authentication authUserByToken() {
        Authentication securityToken = null;
        try {
            User user = userService.findUserByAccessToken(this.token);
            securityToken = new PreAuthenticatedAuthenticationToken(
                    user, null, user.getAuthorities());
        } catch (Exception e) {
            logger.error("Authenticate user by token error: ", e);
        }
        return securityToken;
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
            Authentication authResult) throws IOException, ServletException {
        SecurityContextHolder.getContext().setAuthentication(authResult);
        chain.doFilter(request, response);
    }

和简单的测试:

 @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:spring/test/test-servlet.xml"})
@WebAppConfiguration
public class TagControllerTest {

    private MockMvc mockMvc;

    private TagService tagServiceMock; 

    @Autowired
    private FilterChainProxy springSecurityFilterChain;

    @Resource
    private WebApplicationContext webApplicationContext;

    @Before
    public void setUp() {
        tagServiceMock = mock(TagService.class);
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext)
                .addFilters(this.springSecurityFilterChain)
                .build();
    }

    public TagControllerTest() {
    }

    /**
     * Test of getAllTags method, of class TagController.
     */
    @Test
    public void testGetAllTags() throws Exception {
        List<Tags> tagsList = new ArrayList<>();
        tagsList.add(new Tags((long) 1, "test", 2, 1));
        tagsList.add(new Tags((long) 2, "test2", 4, 0));
        User user = TestUtil.EMPTY_USER;
        String query = "";
        String notIncluded = "";
        Integer limit = 8;
        Integer start = 0;
        Language language = new Language(0);
        Boolean approved = false;

        when(tagServiceMock.findTagsByQuery(user, query, limit, start, language, approved)).thenReturn(tagsList);
        when(tagServiceMock.findTags(user, limit, start, language)).thenReturn(tagsList);



        SecurityContextHolder.getContext().setAuthentication(TestUtil.getPrincipal("ROLE_ADMIN"));

        mockMvc.perform(get("/tags").with(securityContext(SecurityContextHolder.getContext())).header("host", "localhost:80"))
                .andExpect(status().isOk())
                .andExpect(content().contentType(TestUtil.APPLICATION_JSON_UTF8))
                .andExpect(jsonPath("$", hasSize(2)))
                .andExpect(jsonPath("$[0].id", is(1)))
                .andExpect(jsonPath("$[1].id", is(2)))
                .andExpect(jsonPath("$[0].label", is("test")))
                .andExpect(jsonPath("$[1].label", is("test2")))
                .andExpect(jsonPath("$[0].count", is(2)))
                .andExpect(jsonPath("$[1].count", is(4)))
                .andExpect(jsonPath("$[0].approved", is(1)))
                .andExpect(jsonPath("$[1].approved", is(0)));

        verify(tagServiceMock, times(1)).findTagsByQuery(user, query, limit, start, language, approved);
        verifyNoMoreInteractions(tagServiceMock);

    }

问题是,我总是收到 403 -> 拒绝访问。 这是因为 TokenAuthenticationFilter。 如果我使用正确的访问令牌设置名为“Authorization”的标头(正确的意思是实际用户使用),那么它就可以工作。 但我想这不是单元测试应该如何。 那么该怎么办? 如何设置角色并通过安全过滤器?

如果您不进行应包含它的集成测试,则应出于测试目的关闭 Spring 安全性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM