Defender можно представить как формирование охраны замка. Если вы хотите охранять замок, вам потребуется участие guarder, и guarder — это так называемый охранник.
В сервисе существует только один defender, и guarder, тесно связанный с guarder, будет формировать отношение «многие к одному» с defender. Каждый guarder может задавать различные режимы и стратегии для противодействия или фильтрации посетителей и внешних врагов. При одновременном запуске нескольких guarder они будут сотрудничать друг с другом и усердно работать над безопасностью сервиса!
Defender — это синглтон, и мы можем получить его следующим образом:
Defender.getInstance()
Defender больше похож на контейнер, который загружает определённый нами guarder, чтобы помочь нам управлять разрешениями. Мы можем зарегистрировать guarder, вызвав метод реестра:
Defender.getInstance()
.registry(guarder)
.ready()
Видно, что после регистрации guarder мы вызвали метод ready, который является важным. Это сигнал о том, что мы уведомляем defender обо всём готовом. Как только этот метод будет выполнен, defender выполнит работу по инициализации вместе.
Получить Guarder просто, его конструкция является частной, чтобы сделать процесс инициализации более элегантным, а ниже приведён полный экземпляр Guarder:
Guarder.builder(GuarderType.URI)
.pattern("POST /user")
.order(1)
.preventer(caller -> {
return Result.pass();
})
Порядок является значением по умолчанию, с помощью которого можно настроить порядок защиты нескольких guarder, первый из которых можно назвать отрядом смертников. Когда мы вызываем метод builder, нам нужно передать значение перечисления, чтобы указать используемый нами шаблон защиты, который мы рассмотрим позже. Как видите, получить объект guarder так же просто.
Defender предлагает три режима защиты, с разными стилями для разных режимов защитника:
Несмотря на различия, их можно использовать в сочетании с проектом, и мы подробнее рассмотрим каждый шаблон ниже.
Используя шаблон аннотаций, мы должны создать соответствующий экземпляр guarder:
Guarder.builder(GuarderType.ANNOTATION)
.pattern("org.nico.trap.controller")
.preventer(caller -> {
return Result.pass();
})
Далее нам нужно добавить аннотации @access к методам, которые нам нужно защитить:
@Access(AuthConst.LOGIN)
@PostMapping("/")
public ResponseVo<GameFullVo> publishGame(@RequestBody GamePublishVo gameVo) throws TrapException{
GameFullVo gameFullVo = gameService.publishGame(gameVo);
return new ResponseVo<GameFullVo>(ResponseCode.SUCCESS, gameFullVo);
}
Значение, переданное в аннотацию @access, может быть определено как одна константа на основе текущего состояния системы, defender не сделал строгого определения! Формат шаблона под каждым режимом отличается. Для режима аннотаций значение шаблона представляет собой имя пакета, и все шаблоны с @access в этом пакете будут защищены.
Модель выражений более детализирована, чем модель аннотаций, но также более общая. Мы можем получить guarder модели выражения следующими способами:
Guarder.builder(GuarderType.EXPRESSION)
.pattern("* org.nico.trap.controller.UserController.*(..)")
.prevener(caller -> {
return Result.pass();
})
По сравнению с моделью аннотаций формат и значение шаблона сильно различаются, и здесь представлено исполняемое выражение.
Шаблоны URI более интуитивно понятны:
Guarder.builder(GuarderType.URI)
.pattern("POST /user")
.preventer(caller -> {
return Result.pass();
})
Первый абзац — это тип запроса, а второй абзац — адрес запрошенного ресурса. Используется сопоставление в стиле ANT. В целом модель выражения похожа на модель выражения.
В предыдущей дискуссии мы узнали о связи и роли defender и guarder, а также о различных режимах защиты guarder. Теперь мы проведём более глубокий анализ guarder, чтобы лучше и гибче использовать его возможности.
Этот метод требует передачи перечисляемого значения GuarderType для определения режима защиты guarder, и возвращаемое значение будет объектом guarder и единственной инстанцированной записью!
Значение pattern зависит от различных шаблонов защиты. Для одного и того же guarder может быть несколько шаблонов, таких как шаблон URI.
Guarder.builder(GuarderType.URI)
.pattern("POST /user")
.pattern("DELETE /user")
.pattern("* /game")
.preventer(caller -> {
return Result.pass();
})
Метод order определяет значение int, указывающее порядок защиты всех guarder под defender. Чем меньше значение порядка, тем выше приоритет. Значение по умолчанию равно 0.
Метод представлен в объекте интерфейса AbstractPreventer, нам нужно реализовать внутренний метод обнаружения интерфейса для пользовательских правил.
public interface AbstractPreventer {
public Result detection(Caller caller);
}
Далее рассмотрим сценарий, где нам нужно получить токен в заголовке запроса, чтобы определить, защищён ли пользователь от входа, и мы используем режим аннотации для создания объекта guarder.
Guarder.builder(GuarderType.ANNOTATION)
.pattern("org.nico.trap.controller")
.preventer(new AbstractPrevener() {
@Autowired
private AuthComponent authComponent;
@Override
public Result detection(Caller caller) {
String identity = caller.getAccess().value();
if(! identity.equals(AuthConst.VISITOR)) {
UserBo user = authComponent.getUser();
if(user != null) {
if(identity.equals(AuthConst.ADMIN)){
if(user.getRuleType() == null) {
return Result.notpass(new ResponseVo<>(ResponseCode.ERROR_ON_USER_IDENTITY_MISMATCH));
}
}
```
```}else {
return Result.notpass(new ResponseVo<>(ResponseCode.ERROR_ON_LOGIN_INVALID));
}
}
return Result.pass();
})
В приведённом выше классе реализации AbstractPreventer мы используем @autowired, это функция, которую должен поддерживать защитник. Для простой защиты мы можем использовать более лаконичную реализацию лямбда, например, запрос на токен существует.
Guarder.builder(GuarderType.ANNOTATION)
.pattern("org.nico.trap.controller")
.preventer(caller -> {
return caller.getRequest().getHeader("token") == null
? Result.notpass("Token not exist")
: Result.pass();
})
Как видно из приведённого примера, метод защитника возвращает два типа: pass и notpass, и соответствующий экземпляр получается через статический метод Result.
Result.notpass(Object o)
указывает, что защита не нарушена. Этот запрос является незаконным. Переданный параметр o представляет собой сообщение с подсказкой, возвращаемое запрашивающему.Result.pass()
представляет законный запрос.Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )