Как использовать роли в конфигурации безопасности Zuul для защиты маршрутов к микросервисам? - PullRequest
0 голосов
/ 22 апреля 2020

Когда JWT проверен и имя пользователя, пароль и роли извлечены и переданы UsernamePasswordAuthenticationToken, каждый маршрут к каждой службе может быть доступен. Как ограничить доступ к каждому маршруту. Я пробовал с ролями, но они игнорируются. Вот моя безопасность Фильтр конфигурации и авторизации в Zuul:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

    private Environment environment;
    private UserDetailsService service;

    @Autowired
    public SecurityConfig(Environment environment, UserDetailsService service) {
        this.environment = environment;
        this.service = service;
    }

    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable();

        http.headers().frameOptions().disable();
        //.access("hasRole('ROLE_CUSTOMER')") wrong
        http.authorizeRequests()
        .antMatchers(HttpMethod.POST,this.environment.getProperty("api.users.registration.url.path")).permitAll()
        .antMatchers(HttpMethod.POST,this.environment.getProperty("api.users.login.url.path")).permitAll()
        .antMatchers(HttpMethod.POST,this.environment.getProperty("api.customers.registration.url.path")).permitAll()
        .antMatchers("/users/**").hasRole("ADMIN")
        .antMatchers("/customers/details/{id}").hasAnyRole("ADMIN","CUSTOMER")
        .antMatchers("/customers/getAll").hasAnyRole("ADMIN")
        .antMatchers("/customers/update").hasRole("CUSTOMER")
        .antMatchers("/customers/delete/{id}").hasAnyRole("ADMIN","CUSTOMER")
        .antMatchers("/categories/**").hasRole("ADMIN")
        .antMatchers("/sales/**").hasRole("ADMIN")
        .antMatchers("/orders/**").hasRole("ADMIN")
        .antMatchers("/products/getAll").hasAnyRole("ADMIN","CUSTOMER")
        .antMatchers("/products/details/{id}").hasAnyRole("ADMIN","CUSTOMER")
        .antMatchers("/products/update").hasRole("ADMIN")
        .antMatchers("/products/create").hasRole("ADMIN")
        .antMatchers("/products/delete/{id}").hasRole("ADMIN")
        .anyRequest().authenticated()
        .and().addFilterBefore(new AuthorizaionFilter(authenticationManagerBean(),this.environment,this.service), 
                BasicAuthenticationFilter.class);
        //.and().addFilter(new AuthorizaionFilter(authenticationManagerBean(),this.environment,this.service));

        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    }

    @Bean
    public DaoAuthenticationProvider authProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setPasswordEncoder(encoder());
        provider.setUserDetailsService(this.service);

        return provider;

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authProvider());
    }

    @Bean
    public BCryptPasswordEncoder encoder() {

        return new BCryptPasswordEncoder();
    }

}


public class AuthorizaionFilter extends BasicAuthenticationFilter {

    private String headerName;
    private String headerPrefix;
    private String tokenSecret;
    private UserDetailsService service;

    private Environment env;

    //@Autowired
    public AuthorizaionFilter(AuthenticationManager manager, Environment env,UserDetailsService service) {
        super(manager);
        this.env = env;
        this.tokenSecret = this.env.getProperty("token.secret");
        this.headerPrefix = this.env.getProperty("authorization.token.header.prefix");
        this.headerName = this.env.getProperty("authorization.token.header.name");
        this.service = service;

    }

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
            throws IOException, ServletException {

        String authHeader = req.getHeader(this.headerName);

        if (authHeader == null || !authHeader.startsWith(this.headerPrefix)) {

            chain.doFilter(req, res);
            return;
        }

        UsernamePasswordAuthenticationToken auth = this.getAuthentication(req);

        if (auth == null ) {

            chain.doFilter(req, res);
            return;
        }

        SecurityContextHolder.getContext().setAuthentication(auth);
        chain.doFilter(req, res);

    }

    protected UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest req) {

        String token = "";

        Jws<Claims> body = null;

        try {

            String tokenWithPrefix = req.getHeader(this.headerName);

            if (tokenWithPrefix != null) {

                token = tokenWithPrefix.replace(this.headerPrefix, "");

                token = token.trim();

                body = Jwts.parser().setSigningKey(this.tokenSecret).parseClaimsJws(token);
            }

            if (this.headerName == null || body == null || (body.getBody().getExpiration().before(new Date()))) {
                return null;
            } 

            ArrayList<LinkedHashMap<String, String>> map = (ArrayList<LinkedHashMap<String, String>>) body.getBody().get("roles");

            List<GrantedAuthority> roles = new ArrayList<>();

            for (int i = 0; i < map.size(); i++) {

                roles.add(new SimpleGrantedAuthority("ROLE_" + (map.get(i).get("authority")).toUpperCase()));
                // 
            }

            UserDetails details = service.loadUserByUsername(body.getBody().getSubject());

            System.out.println(req.isUserInRole("ROLE_ADMIN"));

            //List<GrantedAuthority> r = (List<GrantedAuthority>) details.getAuthorities();

            return new UsernamePasswordAuthenticationToken(details.getUsername(), details.getPassword(), roles);

            /*UsernamePasswordAuthenticationToken authenticationToken = 
                    new UsernamePasswordAuthenticationToken(body.getBody().getSubject(),null,roles);

            return authenticationToken;*/

        } catch (JwtException | IllegalArgumentException e) {
            System.out.println(e.getMessage());
            throw new JwtAuthenticationException("JWT is expired or invalid!");

        }

    }

}

Я понял, что должен передать учетные данные пользователя в микросервис, к которому я хочу получить доступ, и там нужно проверить роли. Я прочитал, что мне нужно использовать ZuulFilter в Zuul в Чтобы добавить учетные данные в заголовки или добавить заголовок авторизации с помощью JWT, который должен быть проверен в микросервисе и должен быть извлечен роли, а затем использовать их в конфигурации безопасности этой службы. Это правильный путь или есть другой. Пожалуйста, если вы знаете какой-либо примеры всего этого в зууле и в конкретном микросервисе пришлите мне какую-нибудь ссылку. Спасибо

...