繁体   English   中英

Spring Cloud:微服务身份验证通过Eureka Discovery进行,但不适用于Zuul

[英]Spring Cloud: Microservice authentication works through Eureka Discovery, but not through Zuul

我是Spring Cloud的新手。 我正在尝试通过使用Spring Cloud Eureka Discovery和Zuul Gateway构建一些微服务。

我可以通过Zuul网关访问微服务并执行操作,但前提是不涉及安全性。 如果我的微服务是安全的,那么我就无法通过Zuul进行任何操作,因为它不会返回JWT令牌。 如果我通过Eureka发现客户端执行此操作,那么它就像一个魅力。

我的Zuul配置可能有问题吗? 还是我选择了一种无效的方法来保护服务? 提前致谢!

这是我的Zuul网关配置:

Application.class

@SpringBootApplication
@EnableZuulProxy
@EnableDiscoveryClient
public class GatewayServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayServiceApplication.class, args);
    }

    @Bean
    public Filter shallowEtagHeaderFilter() {
        return new ShallowEtagHeaderFilter();
    }
}

application.properties

eureka.client.service-url.defaultZone=http://localhost:8010/eureka/
server.port=8011
zuul.prefix=/services

bootstrap.properties

spring.application.name=gateway-service
# specify where config server is up
spring.cloud.config.uri=http://localhost:8001

这是我的微服务JWT和安全性配置:

WebSecurityConfig.class

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure (HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
                .antMatchers(HttpMethod.POST, "/login").permitAll()
                .anyRequest().authenticated()
                .and()
                // We filter the api/login requests
                .addFilterBefore(new JWTLoginFilter("/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class)
                // And filter other requests to check the presence of JWT in header
                .addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    protected void configure (AuthenticationManagerBuilder auth) throws Exception {
        // Create a default account
        auth.inMemoryAuthentication()
                .withUser("**")
                .password("**")
                .roles("**");
    }
}

TokenAuthenticationService.class

public class TokenAuthenticationService {
    static final long EXPIRATIONTIME = 864_000_000; // 10 days
    static final String SECRET = "*";
    static final String TOKEN_PREFIX = "Bearer";
    static final String HEADER_STRING = "Authorization";

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

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

            return user != null ?
                    new UsernamePasswordAuthenticationToken(user, null, Collections.emptyList()) :
                    null;
        }
        return null;
    }
}

JWTLoginFilter.class

public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {

    public JWTLoginFilter (String url, AuthenticationManager authManager) {
        super(new AntPathRequestMatcher(url));
        setAuthenticationManager(authManager);
    }

    @Override
    public Authentication attemptAuthentication (HttpServletRequest req, HttpServletResponse res)
            throws AuthenticationException, IOException, ServletException {

        AccountCredentials creds = new ObjectMapper().readValue(req.getInputStream(), AccountCredentials.class);
        return getAuthenticationManager().authenticate(
                new UsernamePasswordAuthenticationToken(
                        creds.getUsername(),
                        creds.getPassword(),
                        Collections.emptyList()
                )
        );

    }

    @Override
    protected void successfulAuthentication (HttpServletRequest req,
                                             HttpServletResponse res,
                                             FilterChain chain,
                                             Authentication auth)
            throws IOException, ServletException {
        TokenAuthenticationService.addAuthentication(res, auth.getName());
    }
}

JWTAuthenticationFilter.class

public class JWTAuthenticationFilter extends GenericFilterBean {
    @Override
    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);
    }
}

尝试定义以下内容。

zuul.sensitiveHeaders=Cookie,Set-Cookie

在zuul中,Cookie,Set-Cookie和Authroization标头是默认的敏感标头。 如果您想在api服务器中进行Authroization标头,则需要重新定义它,而不需要上面的Authroization标头。

您也可以为每条路线定义它。 请参考文档: http : //cloud.spring.io/spring-cloud-netflix/spring-cloud-netflix.html [Cookies和敏感标题]

暂无
暂无

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

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