Как я могу включить запрос только для собственной конечной точки пользователя - PullRequest
0 голосов
/ 15 декабря 2018

У меня есть конечная точка отдыха, например: / users / {userId} / что-то

Я реализовал аутентификацию с использованием oauth2.Мой WebSecurityConfig выглядит следующим образом:

protected void configure(HttpSecurity http) throws Exception {
    http
    .authorizeRequests()
    .anyRequest().authenticated()
    .and()
    .formLogin()
    .loginPage("/login").permitAll();
}

Как я могу разрешить пользователям доступ только к своей собственной конечной точке (например, пользователь с идентификатором 100 может получить доступ только к /users/100/something), не имея возможности видеть другую конечную точку (например, /users/200/something)?

Возможно ли это?

1 Ответ

0 голосов
/ 15 декабря 2018

Существует много способов решения этой проблемы, но я выбрал три решения для ее устранения.

Настраиваемое выражение безопасности

Я бы порекомендовал подход на основе пользовательских аннотаций безопасности.Это может включать реализацию пользовательского выражения безопасности, связанного обработчика выражений и конфигурации безопасности метода.Следующая аппроксимация будет немного проще, если это слишком много для вас.

public class UserIdentityMethodSecurityExpressionRoot 
    extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {

    public UserIdentityMethodSecurityExpressionRoot(Authentication authentication) {
        super(authentication);
    }

    public boolean userIdentity(Long userId) {
        User user = ((UserPrincipal) this.getPrincipal()).getUser();
        return user.getId() == userId;
    }
}

Остальные конечные точки или методы обслуживания могут быть аннотированы вновь созданным выражением безопасности:

@PreAuthorize("userIdentity(#userId)")
@GetMapping
@ResponseBody
public Resource fineOne(@PathVariable Long userId) {
    return resourceService.findOne(id);
}

Обратите внимание, что userId должен быть предоставлен где-то , как @PathVariable или @RequestParam.Затем Spring Security проверит, соответствует ли текущий пользователь указанному userId и возвращает 403 в противном случае.

Полный пример доступен здесь и был адаптирован в этом вопросе для вашегоцели.

SpEL

Вы также можете использовать SpEL, что немного проще:

@PreAuthorize("#userId == principal.getId()")
@GetMapping
@ResponseBody
public Resource fineOne(@PathVariable Long userId) {
    return resourceService.findOne(id);
}

Другие соображения

Вы также можете делать всеработать самостоятельно и получить более быстрый результат, не определяя пользовательское выражение с помощью SecurityContextHolder.

public static void checkUserIdentity(Long userId) {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    // user did not provide a token
    if(auth == null) {
        throw new AccessDeniedException(); 
    }      
    UserDetails details = (UserDetails) auth.getPrincipal();
    if(userId != details.getId()) {
        throw new AccessDeniedException(); 
    }
} 

и используя его как:

@GetMapping
@ResponseBody
public Resource fineOne(@PathVariable Long userId) {
    SecurityUtils.checkUserIdentity(userId)
    return resourceService.findOne(id);
}

Почему это работает?SecurityContextHolder будет вводить текущий участник, если вы правильно настроили безопасность Spring.По умолчанию аутентификация привязана к текущему потоку выполнения и будет сброшена, если запрос был обработан или обнаружил исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...