Можно ли этого добиться в Spring MVC с Spring Security?
@Override WebSecurityConfigurerAdapter.configure (HttpSecurity)
@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.mvcMatchers("/users/{authentication.principal.username}").hasAnyRole(ADMIN, MANAGER)
.antMatchers("/users/**").hasRole(ADMIN)
.anyRequest().authorized()
...
}
/users/** является закрытой областью и должен быть доступен только администраторам. Но менеджеры по-прежнему должны иметь возможность видеть свой собственный профиль (/users/user_with_manager_role) и только свой собственный профиль, а не профили других пользователей (независимо от их роли).
Я нашел решение в ответе Эндрю. Мой код теперь выглядит так:
WebSecurityConfigurerAdapter
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // added this annotation
public class SecurityConfig extends WebSecurityConfigurerAdapter
@Override WebSecurityConfigurerAdapter.configure (HttpSecurity)
@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
// removed /users handling
.anyRequest().authorized()
...
}
UsersController
@Controller
@RequestMapping("/users")
public class UsersController
{
@GetMapping("{username}")
@PreAuthorize("authentication.principal.username == #username) || hasRole('ADMIN')")
public String usersGet(@PathVariable("username") String username)
{
// do something with username, for example get a User object from a JPA repository
return "user";
}
}




Боюсь, это невозможно: когда эта конфигурация настраивается, у нее нет информации о {authentication.principal.username}, которая будет решена в какой-то момент в будущем.
Но Spring дает вам набор встроенных выражения безопасности метода, с помощью которых вы можете аннотировать свои методы.
Начиная с простого выражения вроде @PreAuthorize("hasRole('ADMIN')"), вы можете получить собственное выражение:
@XMapping(path = "/users/{username}")
@PreAuthorize("@yourSecurityService.isMyPage(authentication.principal, #username)")
public void yourControllerMethod(@PathVariable String username);
@yourSecurityService.isMyPage(authentication.principal, #username) относится к вашему методу @Servicepublic boolean isMyPage(Principal, String).
Как насчет чего-то вроде этого:
@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/myself").hasAnyRole(ADMIN, MANAGER)
.antMatchers("/users/**").hasRole(ADMIN)
.anyRequest().hasAnyRole(ADMIN, MANAGER)
...
}
@RequestMapping(value = "/myself", method = RequestMethod.GET)
public Profile getMyself() {
// return the profile of the loged in user
}
С помощью этого менеджера и администраторы могут получить свой собственный профиль, а администраторы также могут запросить другие профили с помощью /users/{username}.
Не редактируйте решение своего вопроса. Просто добавьте новый ответ на свой вопрос. Следовательно, я откатил вашу правку. Вы можете скопировать свой ответ из истории, чтобы добавить новый ответ.