Внешняя конфигурация безопасности Spring

Обычно SecurityConfig мы делаем как

protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/index.html").permitAll()
            .antMatchers("/profile/**").authenticated()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/management/**").hasAnyRole("ADMIN", "MANAGER")
            .antMatchers("/api/public/test1").hasAuthority("ACCESS_TEST1")
            .antMatchers("/api/public/test2").hasAuthority("ACCESS_TEST2")
            .antMatchers("/api/public/users").hasRole("ADMIN")
            .and()
            .httpBasic();
}

Я хочу получить эти конечные точки ("/api/public/test2") и необходимые полномочия "ACCESS_TEST2" из файла свойств или БД (внешняя конфигурация SecurityConfig).

Могу ли я это сделать? как мне это сделать?

2
0
301
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Да, конечно, настройте UrlFilterInvocationSecurityMetadataSource для реализации FilterInvocationSecurityMetadataSource и переопределите getAttributes() метод, чтобы получить информацию о разрешениях роли, необходимую для доступа к URL-адресу.

В этих статьях разрешение на доступ к URL-адресу будет предоставлено ролью пользователя. Нажмите для первой статьи!Нажмите, чтобы перейти ко второй статье!

я не верю, что он хотел динамически настраивать разрешения во время выполнения. Он хотел внедрить статическую конфигурацию.

Toerktumlare 25.12.2020 08:16
Ответ принят как подходящий

Я не знаю, есть ли механизм безопасности для загрузки из файла, поэтому предлагаю собственную реализацию:

@Configuration
@EnableWebSecurity
@ConfigurationProperties("secure")
@PropertySource(value = "classpath:security-config.yml", factory = YamlPropertySourceFactory.class)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private Map<String, List<String>> urlToAuthorityMapping;
    private Map<String, List<String>> urlToRoleMapping;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.authorizeRequests();

        urlToAuthorityMapping.forEach((urlPattern, authorities) ->
                registry.antMatchers(urlPattern).hasAnyAuthority(authorities.toArray(new String[0])));

        urlToRoleMapping.forEach((urlPattern, roles) ->
                registry.antMatchers(urlPattern).hasAnyRole(roles.toArray(new String[0])));

        registry.and().httpBasic();
    }

    public void setAuthorities(Map<String, List<String>> authorities) {
        this.urlToAuthorityMapping = invert(authorities);
    }

    public void setRoles(Map<String, List<String>> roles) {
        this.urlToRoleMapping = invert(roles);
    }

    private Map<String, List<String>> invert(Map<String, List<String>> source) {
        Map<String, List<String>> invertedMapping = new HashMap<>();
        for (Map.Entry<String, List<String>> entry : source.entrySet()) {
            String authority = entry.getKey();
            List<String> urlPattens = entry.getValue();
            for (String urlPattern : urlPattens) {
                List<String> authorities = invertedMapping.getOrDefault(urlPattern, new ArrayList<>());
                authorities.add(authority);
                invertedMapping.put(urlPattern, authorities);
            }
        }
        return invertedMapping;
    }
}
public class YamlPropertySourceFactory implements PropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) {
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        factory.setResources(encodedResource.getResource());

        Properties properties = factory.getObject();

        return new PropertiesPropertySource(encodedResource.getResource().getFilename(), properties);
    }
}

безопасность-config.yml

secure:
  authorities:
    ADMIN:
      - /api/public/users
      - /admin/**
    ACCESS_TEST2:
      - /api/public/test2
    MANAGER:
      - /api/public/users
  roles:
    ACCESS_TEST1:
      - /api/public/test1
    ACCESS_TEST2:
      - /api/public/test2
  authenticated:
    - /profile/**
  permitAll:
    - /public-content/**

Другие вопросы по теме