Когда 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, который должен быть проверен в микросервисе и должен быть извлечен роли, а затем использовать их в конфигурации безопасности этой службы. Это правильный путь или есть другой. Пожалуйста, если вы знаете какой-либо примеры всего этого в зууле и в конкретном микросервисе пришлите мне какую-нибудь ссылку. Спасибо