пружинная пользовательская аннотация для проверки заголовков - PullRequest
0 голосов
/ 26 февраля 2019

Я использую spring-boot-1.5.10, и я использую Spring-Security в своем приложении.Я хотел бы создать пользовательскую аннотацию, которая должна использовать держатель securityContext ... Позвольте мне уточнить мой вопрос с примером кода.

curl -X GET -H "role: READ" -H "Content-Тип: application / json "-H" Принять: application / json "-H" имя приложения: пример "-H" идентификатор приложения: пример "-H" идентификатор клиента: 123 "-H" рынок: EN "-H "код страны: EN" -H "Accept-Language: application / json" -H "Cache-Control: no-cache" "http://localhost:9992/api/v1/apps"

Контроллер

@GetMapping("/apps")
@PreAuthorize("hasAnyAuthority('ROLE_READ', 'ROLE_WRITE')")
public ResponseEntity<List<Apps>> getApps(@AuthenticationPrincipal AppAuthentication appAuthentication) {
    if(appAuthentication.isGrantedAnyOf("ROLE_READ") && isBlank(appAuthentication.getAppContext().customerId())) {
        throw new IllegalArgumentException("Missing header customerId");
    }
    if(appAuthentication.isGrantedAnyOf("ROLE_WRITE") && isBlank(appAuthentication.getAppContext().customerId()) && isBlank(appAuthentication.getAppContext().appId())) {
        throw new IllegalArgumentException("Missing header customerId & AppId");
    }
    //write business logic here
}

spring-security preAuthorize только проверяет, разрешены ли роли. Кроме того, я могу улучшить аннотацию preAuthorize, но она характерна для многих микросервисов, а также у меня нетразрешение касаться области безопасности. Итак, я хотел бы создать пользовательскую аннотацию. Мы должны настроить роли и заголовки для проверки для конкретных ролей. Как показано ниже

@GetMapping("/apps")
@PreAuthorize("hasAnyAuthority('ROLE_READ', 'ROLE_WRITE')")
@ValidateHeaders("role=ROLE_READ",value={"customerId","app-id"})
public ResponseEntity<List<Apps>> getApps(@AuthenticationPrincipal AppAuthentication appAuthentication) {
    //write business logic here
}

Любая подсказка будет действительно заметной.

1 Ответ

0 голосов
/ 26 февраля 2019

Disclamer - я работал с весенней загрузкой 2, поэтому не все может быть применимо для вас

Это урезанная версия того, что я реализовал некоторое время назад.Я предлагаю реализовать перечисления для ролей и значений.

Вы не можете делать перенаправления из аннотаций @before, поэтому вам нужно вызвать исключение и перехватить его с помощью глобального обработчика ex, перенаправление оттуда.

Также рассмотрите возможность добавления к аннотации необязательных полей - в случае нескольких ролей, сопоставьте все или одно, путь перенаправления, тип исключения для вызова в случае отсутствия доступа.Затем в обработчике исключений вы можете делать перенаправления в зависимости от того, какое исключение было вызвано.Поскольку вы выполняете перенаправления из обработчика gloabl ex, если вы добавите путь перенаправления, вам придется связать его с исключением, которое вы выбрасываете, то есть вам понадобятся пользовательские исключения.

Аннотация

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidateHeaders {

    Roles[] roles();
    String[] values();
}

Aspect Class

@Aspect
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired)) //Autowired annotated lombok generated constructor
public class ValidateHeadersAspect {


    private final @NonNull HttpServletRequest request; //Inject request to have header access
    private final @NonNull UserService userService;//Your user service here

    //Aspect can be placed on clas or method
    @Before("within(@com.org.package.ValidateHeaders *) || @annotation(com.org.package.ValidateHeaders)") 
    public void validateAspect(JoinPoint joinPoint) throws Throwable {

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        HasAccess validateHeaders = method.getAnnotation(ValidateHeaders.class);

        if(validateHeaders == null) { //If null it was a class level annotation
            Class annotatedClass = joinPoint.getSignature().getDeclaringType();
            validateHeaders = (ValidateHeaders)annotatedClass.getAnnotation(ValidateHeaders.class);
        }

        Roles[] roles = validateHeaders.roles(); //Roles listed in annotation
        String[] values = validateHeaders.values(); //Values listed in 


        //Validate request here ... determine isAuthorised


        if( !isAuthorized ){
            throw new HeaderAuthrizationException()
        }
    }

}

Обработчик исключений

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(HeaderAuthrizationException.class)
    public RedirectView HeaderAuthrizationException(HeaderAuthrizationException ex) {
        return new RedirectView("/redirect");
    }

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