Spring / Spock - 身份验证的集成测试

时间:2017-07-17 11:15:27

标签: spring groovy spring-security integration-testing spock

我想在我的应用程序中测试受保护的端点,我想在每次测试之前登录,获取令牌并在下次测试中使用此令牌。

@ContextConfiguration
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Stepwise
class IntegrationSpec extends Specification {

    @Autowired
    private TestRestTemplate rest

    @Autowired
    private String token

    @Shared
    private HttpEntity request

    def setup() {
        UserData userData = new UserData("Username", "Password");

        def response = rest.postForEntity('/login', userData, Object)

        String tempToken = response.getHeaders().get('Authorization')
        // remove prefix of token
        this.token = tempToken.substring(tempToken.lastIndexOf(" ") + 1)

        String loginToken = token.substring(token.lastIndexOf(" ") + 1)

        final MultiValueMap<String, String> headers = new LinkedMultiValueMap<>()
        headers.add('Authorization', loginToken)
        this.request = new HttpEntity(headers)
    }

    def 'protected resource test'() {
        when:
            def response = rest.exchange('/protected/resource', HttpMethod.GET, request, new ParameterizedTypeReference<String>() {})

        then:
            response.getStatusCode() == HttpStatus.OK
    }
}

但是我收到了错误:

io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.
    at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:354) ~[jjwt-0.7.0.jar:0.7.0]
    at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:481) ~[jjwt-0.7.0.jar:0.7.0]
    at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:541) ~[jjwt-0.7.0.jar:0.7.0]
    at mypackages.TokenAuthenticationService.getAuthentication(TokenAuthenticationService.java:39) ~[classes/:na]
    at mypackages.filters.JWTAuthenticationFilter.doFilter(JWTAuthenticationFilter.java:23) ~[classes/:na]

我的TokenService看起来如下:

public class TokenAuthenticationService {

    static final long EXPIRATION_TIME = 10000000;
    static final String SECRET = "secret_word";
    static final String TOKEN_PREFIX = "Bearer";
    static final String HEADER_STRING = "Authorization";

    public static void addAuthentication(HttpServletResponse res, String username) {
        String JWT = Jwts.builder()
                .setSubject(username)
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .compact();
        res.addHeader(HEADER_STRING, TOKEN_PREFIX + " " + JWT);
    }

    public static Authentication getAuthentication(HttpServletRequest request) {
        String token = request.getHeader(HEADER_STRING);
        if (token != null) {
            String user = Jwts.parser()
                    .setSigningKey(SECRET)
                    .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
                    .getBody()
                    .getSubject();

            return user != null ?
                    new UsernamePasswordAuthenticationToken(user, null, new ArrayList<GrantedAuthority>()) :
                    null;
        }

        return null;
    }
}

JWTAuthenticationFilter:

public class JWTAuthenticationFilter extends GenericFilterBean {

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        Authentication authentication = TokenAuthenticationService.getAuthentication((HttpServletRequest) servletRequest);

        SecurityContextHolder.getContext()
                .setAuthentication(authentication);

        filterChain.doFilter(servletRequest, servletResponse);
    }
}

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public UserDetailsService customUserDetailsService() {
        return new CustomUserDetailsService();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers(HttpMethod.POST, "/login").permitAll()
                .antMatchers(HttpMethod.POST, "/register").permitAll()
                .anyRequest().authenticated()
                .and()
                .addFilterBefore(new JWTLoginFilter("/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService());
    }
}

0 个答案:

没有答案