Spring Security позволяет каждому пользователю видеть свой профиль, но никому другому

Можно ли этого добиться в 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";
    }
}

Не редактируйте решение своего вопроса. Просто добавьте новый ответ на свой вопрос. Следовательно, я откатил вашу правку. Вы можете скопировать свой ответ из истории, чтобы добавить новый ответ.

dur 13.10.2018 20:13
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
8
1
1 382
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Боюсь, это невозможно: когда эта конфигурация настраивается, у нее нет информации о {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}.

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