Обычно 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).
Могу ли я это сделать? как мне это сделать?
Да, конечно, настройте UrlFilterInvocationSecurityMetadataSource
для реализации FilterInvocationSecurityMetadataSource
и переопределите getAttributes()
метод, чтобы получить информацию о разрешениях роли, необходимую для доступа к URL-адресу.
В этих статьях разрешение на доступ к URL-адресу будет предоставлено ролью пользователя. Нажмите для первой статьи!Нажмите, чтобы перейти ко второй статье!
Я не знаю, есть ли механизм безопасности для загрузки из файла, поэтому предлагаю собственную реализацию:
@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/**
я не верю, что он хотел динамически настраивать разрешения во время выполнения. Он хотел внедрить статическую конфигурацию.