В последнее время многие студенты сообщают, что проекту необходимо иметь дело с разрешениями на доступ к данным, но они не знают, как правильно с этим справиться. В этой заметке представлена более общая и легко расширяемая схема проектирования разрешений на доступ к данным для решения этой проблемы.
статус квоВ настоящее время популярная структура разрешений уже поддерживает разрешение данных, но ее необходимо настроить в интерфейсе и методе, а масштабируемость не очень хорошая, так как же мы можем максимизировать масштабируемость?
Придумать несложно: поместить контроль разрешений данных в базу данных, и сначала определить, есть ли доступ у интерфейса при перехвате разрешения.После того, как у интерфейса есть доступ, то определить, имеют ли указанные параметры право на использование настроенные условия.значение. (Чтобы сделать это более продвинутым, вы можете проверить возвращаемый результат. Если доступ к объекту, содержащему определенное значение, запрещен, он также рассматривается как несанкционированный доступ. Эта ситуация пока не рассматривается в этой заметке). Как это сделать?
Дизайн базы данныхДавайте начнем с дизайна таблицы базы данных, сначала определим структуру таблицы управления правами доступа к данным:
CREATE TABLE `sys_acl_data` (
`id` int(11) NOT NULL,
`acl_id` int(11) NOT NULL COMMENT '对应权限表主键',
`status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '状态,1:可用,0:不可用',
`param` varchar(20) NOT NULL DEFAULT '' COMMENT '参数',
`operation` int(11) NOT NULL DEFAULT 0 COMMENT '操作类型,0;等于,1:大于,2:小于,3:大于等于,4:小于等于,5:包含,6:介于之间,。。。',
`value1` varchar(100) NOT NULL DEFAULT '0',
`value2` varchar(100) NOT NULL DEFAULT '0',
`next_param_op` int(11) NOT NULL DEFAULT 0 COMMENT '后续有参数时连接的关系,0:没有其他参数控制,1:与&&,2:或||',
`seq` tinyint(4) NOT NULL DEFAULT '0' COMMENT '顺序',
PRIMARY KEY (`id`),
INDEX `idx_acl_id` USING BTREE (`acl_id`)
) ENGINE=`InnoDB` COMMENT '数据权限表';
Подробно опишите значение каждого поля:
идентификатор первичного ключа;
acl_id сопоставляет первичный ключ таблицы точек разрешений, который представляет, для какой точки разрешений предназначена каждая строка записей;
статус показывает, действительна ли текущая конфигурация, что удобно для временной активации и деактивации;
param представляет имя параметра, который необходимо проверить, что позволяет запросу иметь несколько параметров для участия в проверке данных; если параметры сложные, например, содержащие объекты, определенные параметры могут быть в форме многоуровневых abc , рекомендуется не слишком усложнять
операция представляет правила перехвата данных, используя числа для обозначения равенства, больше, меньше, больше или равно, меньше или равно, включительно, между и т. д., вы можете увеличивать или уменьшать поддерживаемые правила перехвата в соответствии с твои нужды
значение1 и значение2 используются для формирования реляционного выражения с параметром и операцией, например: 1
Поле next_param_op используется по мере необходимости.Если точка разрешения поддерживает несколько правил данных, соедините операции между двумя правилами, || или &&
Поле seq используется для порядка, когда точка разрешения содержит несколько правил разрешения данных.
Предположим, что есть такой фрагмент данных, тогда его значение: точка доступа, id которой равен 1 (acl_id), настроена с допустимым (status=1) правилом данных, правило такое: значение входящего параметра id (param ) должно быть больше (операция) 10 (значение1)
Логика проверки разрешений на доступ к даннымПосле структуры таблицы следующим шагом будет добавление интерфейсов для обновления и получения данных, а затем страница для отображения и добавления к ней операций, здесь я не буду занимать больше места и сосредоточусь на обработке логики . . .
курс разрешенияЯ не буду повторять базовое управление и перехват разрешений точек разрешений в нативной реализации набора управления разрешениями в этом разделе.Достаточно посмотреть видео и код.Здесь я сосредоточусь на том, как выполнять данные разрешения на существующих разрешениях .расширение. Во-первых, дайте основной код перехвата URL-адресов и проверки разрешений (вы должны быть в состоянии понять это, взглянув только на этот код, не вникая в детали курса):
自定义filter拦截url判断权限核心代码:
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String servletPath = request.getServletPath();
Map requestMap = request.getParameterMap();
if (exclusionUrlSet.contains(servletPath)) {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
SysUser sysUser = RequestHolder.getCurrentUser();
if (sysUser == null) {
log.warn("someone visit {}, but no login, parameter:{}", servletPath, JsonMapper.obj2String(requestMap));
noAuth(request, response);
return;
}
SysCoreService sysCoreService = ApplicationContextHelper.popBean(SysCoreService.class);
if (!sysCoreService.hasUrlAcl(servletPath)) {
log.warn("{} visit {}, but no login, parameter:{}", JsonMapper.obj2String(sysUser), servletPath, JsonMapper.obj2String(requestMap));
noAuth(request, response);
return;
}
filterChain.doFilter(servletRequest, servletResponse);
return;
}
实际判断一个url是否可访问的核心代码:
public boolean hasUrlAcl(String url) {
if (isSuperAdmin()) { // 超级管理员直接允许访问
return true;
}
List<SysAcl> aclList = sysAclMapper.getByUrl(url); // 取出符合条件的权限点
if (CollectionUtils.isEmpty(aclList)) {
return true;
}
List<SysAcl> userAclList = getCurrentUserAclListFromCache();
Set<Integer> userAclIdSet = userAclList.stream().map(acl -> acl.getId()).collect(Collectors.toSet());
boolean hasValidAcl = false;
// 规则:只要有一个权限点有权限,那么我们就认为有访问权限
for (SysAcl acl : aclList) { // ----------------------------------------------------- ①
// 判断一个用户是否具有某个权限点的访问权限
if (acl == null || acl.getStatus() != 1) { // 权限点无效
continue;
}
hasValidAcl = true;
if (userAclIdSet.contains(acl.getId())) {
return true; // ------------------------------------------------------ ②
}
}
if (!hasValidAcl) {
return true; // ------------------------------------------------------- ③
}
return false;
}
Из ① в коде вы можете получить фактическую точку разрешения для оценки. При оценке того, что указанная точка доступа имеет разрешение на доступ, необходимо добавить проверку разрешения данных в ② и ③ кода.
Теперь, когда вы хотите проверить параметры, вам нужно передать параметры в метод hasUrlAcl. В методе doFilter Map requestMap = request.getParameterMap(); requestMap — это список параметров URL-адреса Этот метод не полностью применим к некоторым специальным сообщениям, таким как передача параметров в формате json в теле. Способ передачи параметров методу в реальном проекте может быть обработан в соответствии с фактическим определением интерфейса проекта.
Когда hasUrlAcl получает параметр и решает, что указанная точка доступа имеет доступ, перейдите к таблице sys_acl_data, чтобы запросить список допустимых правил в соответствии с acl_id, и оцените каждый элемент один за другим.Обратите внимание на обработку многих деталей здесь. 1. Интерпретация одного правила, 2. Логические И и ИЛИ между несколькими правилами, 3. Интерпретация параметров с иерархическими уровнями (abc), на практике сложность обработки можно определить по определению и спецификации интерфейса в проект. После этой реализации, когда URL-адрес имеет доступ, нет правила данных или проверка правила данных пройдена, URL-адрес действительно авторизован для доступа.
В это время кто-то обязательно спросит, как мне перехватить права доступа к данным, когда мой интерфейс определен как этот /a/{id}.json? На самом деле, интерфейс этого метода может быть поддержан небольшими корректировками в ходе курса, которые заключаются в следующем:
SysAclMapper.xml:
<select id="getByUrl" parameterType="string" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List" />
FROM sys_acl
WHERE url = #{url} <!-- url is not null and url != '' and #{url} REGEXP url-->
</select>
Содержимое комментария должно включать регулярное сопоставление, которое должно соответствовать URL-адресу через регулярность. Здесь используйте URL-адрес не нулевой и URL-адрес != '' и #{url} URL-адрес REGEXP вместо url = #{url} , и затем настройте каждую точку разрешения.Достаточно использовать обычный, чтобы настроить URL-адрес каждой точки разрешения.Например, когда URL-адрес настроен для проверки разрешений, он может быть настроен как /a/[5|6].json. Конечно, у этого метода есть определенные требования к регулярному выражению администратора полномочий. В настоящее время точки доступа, которые не могут быть проверены при получении квалифицированных URL-адресов, не могут быть получены. Если вы не можете получить его, вы не можете напрямую рассматривать его как сделку. Вы можете рассмотреть возможность настройки разрешения с подстановочным знаком (/a/*.json), когда столкнетесь с этим. Каждый раз, когда вы сопоставляете такой URL-адрес с подстановочным знаком, вы должны убедитесь, что он соответствует содержащему регулярному. Проверка считается только разрешением. Детали этого могут быть обработаны по-разному самостоятельно, здесь только общая идея.
конецДавайте сначала поговорим о разрешениях данных.Лично я думаю, что вышеописанный метод будет относительно лучше с точки зрения масштабируемости, и он не очень сложен в реализации.Если у вас есть какие-либо вопросы, пожалуйста, укажите.
Другие примечания о разрешении
Реформирование процесса управления полномочиями на фоне операций электронной коммерции
Пользовательский тег JSP автоматически завершает процесс перехвата разрешений для кнопки страницы.