Spring Security использует значение переменной в классе для аутентификации
Я использую Spring Security в своем приложении. Я аутентифицирую API на основе роли (ADMIN, USER). Существует одна конечная точка API, к которой я хотел бы ограничить доступ, используя значение переменной, переданной ей в качестве параметра.
я имею
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable().exceptionHandling().authenticationEntryPoint(this.unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/api/**").authenticated()
.anyRequest().permitAll();
httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
}
У меня звонок
@PostMapping("/something")
public ResponseEntity<BotResponse> handleRequest(@Valid @RequestBody SomeClass someClass) {
// if someClass.getSomeValue() is not present in the User permissions, then it should give an unauthorized response.
return value(someClass);
}
Пользователь в Spring Security - это:
public Class User {
String userId;
String userName;
String authorities;
List<String> someList;
//Getters and setters for variables
}
И используется SomeClass:
public Class SomeClass {
String someValue;
String userName;
...
// Getters and Setters
}
Как я не разрешаю пользователям на основе, если значение someClass.getSomeValue присутствует в someList пользователя?
2 ответа
Возможно, вы могли бы сделать такую авторизацию с помощью глобального метода безопасности Spring.
Чтобы использовать авторизацию на уровне метода, вам нужно добавить следующую аннотацию в ваш класс конфигурации безопасности.
@EnableGlobalMethodSecurity(prePostEnabled = true)
Тогда подать заявку @PreAuthorize
используя Spring Expression Language, к вашей конечной точке. Что-то вроде..
@PostMapping("/something")
@PreAuthorize("@someService.checkUserAccess(principal, #someClass)")
public ResponseEntity<BotResponse> handleRequest(@Valid @RequestBody SomeClass someClass) {
// if someClass.getSomeValue() is not present in the User permissions, then it should give an unauthorized response.
return value(someClass);
}
@someService
это bean-компонент, который вы бы автоматически подключали в Controller и определяли метод checkUserAccess() в этом файле. Что-то вроде..
public boolean checkUserAccess(Pricipal principal, SomeClass someClass) {
// here you can fetch your full user object from db or session (depending on your application architecture)
// apply what ever logic you want to apply, return true if user has access and false if no.
}
Примечание / предложение - Вы можете добавить это checkUserAccess()
метод существующего пользовательского сервиса, если ваш дизайн приложения это позволяет, и автоматическое подключение пользовательского сервиса в контроллере.
Что касается вашего вопроса, один из подходов состоит в том, чтобы получить UserDetails, сохраненные в вашем контексте аутентификации Spring Security, а затем проверить соответствующие данные в этом объекте контекста по значению, переданному в качестве параметра. Я предполагаю, что у вас есть все необходимые значения, хранящиеся в контексте безопасности.
Эта проверка может быть выполнена в самом коде конечной точки (если у вас есть небольшое количество таких API). Если существует несколько API-интерфейсов, для которых требуется одна и та же логика, вам придется реализовать либо фильтр, который фильтрует только эти API-интерфейсы (config может быть записан в web.xml), либо pointcut(через AOP).