SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 20.05.2010 21:24:23

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Поведение CURRENT_USER()

Сегодня столкнулся с проблемой, связанной с CURRENT_USER.
Он, оказывается, в процедурах возвращает данные пользователя, который определил объект. sad
Очень весело, учитывая то, что большая часть процедур определены под root и проверяют права по имени пользователя...

Within a stored program or view, CURRENT_USER() returns the account for the user who defined the object (as given by its DEFINER value). This applies to stored programs as of MySQL 5.0.10 and to views as of MySQL 5.0.24. (For older versions, CURRENT_USER() returns the account for the object's invoker.) For stored procedures and functions and views defined with the SQL SECURITY INVOKER characteristic, CURRENT_USER() returns the object's invoker.

Проблема в том, что просто заменить на USER() я не могу, т.к. у меня ключи в таблицах - это User/Host (как в mysql.user).
Мне нужна запись в таблице, соответствующая клиенту, вызвавшему объект.
А USER() возвращает хост, с которого клиент подключился.
Т.е. есть:

Код:

mysql> select CURRENT_USER();;
+----------------+
| CURRENT_USER() |
+----------------+
| root@%         |
+----------------+

mysql> select USER();;
+----------------+
| USER()         |
+----------------+
| root@localhost |
+----------------+

Есть ли какая-то альтернатива CURRENT_USER(), которая возвращает данные вызвавшего объект?

Отредактированно Артём Н. (20.05.2010 21:24:52)


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#2 20.05.2010 21:35:37

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Поведение CURRENT_USER()

Нету, но и смысла использовать CURRENT_USER нету. Не нужно смешивать
пользователей БД и пользователей Вашего приложения. Это разные сущности,
и они должны обрабатываться по разному. Кстати, в Вашем случае, если Вы
все-таки хотите смешивать эти сущности, нужно поступить так, как подразу-
мевается структурой СУБД — давать права на запуск процедуры тому, кто
может ее запускать, а не проверять пользователя внутри.

Неактивен

 

#3 20.05.2010 21:46:39

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Поведение CURRENT_USER()

Не нужно смешивать пользователей БД и пользователей Вашего приложения.

Мне от этого никуда не деться, поскольку, у меня не web-приложение.
Каждый пользователь должен иметь свой аккаунт в СУБД.

Кстати, в Вашем случае, если Вы
все-таки хотите смешивать эти сущности, нужно поступить так, как подразу-
мевается структурой СУБД — давать права на запуск процедуры тому, кто
может ее запускать, а не проверять пользователя внутри.

Это не очень хорошая идея, хотя бы потому, что администратору приложения придётся давать права на БД mysql.
Плюс, это сложно реализуется. Гораздо проще иметь таблицу "высокоуровневых" прав, чем давать права на запуск процедур. Например, у меня есть право на заведение договора. Договор заводится процедурой. Права на запуск - как-то не очень. Плюс, к тому же, в зависимости от наличия других прав, процедура может изменять своё поведение.

А возможно ли как-то реализовать функционал CURRENT_USER() средствами SQL?


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#4 20.05.2010 22:04:08

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Поведение CURRENT_USER()

Во так делать, по ходу, очень криво:

Код:

CREATE
DEFINER = 'root'@'%'
PROCEDURE GetCurUser(OUT user_name CHAR(16), OUT host_name CHAR(60))
READS SQL DATA
SQL SECURITY INVOKER
COMMENT 'Получение текущего пользователя'
BEGIN
  select substring_index(user(),"@", 1),
    substring_index(user(),"@", -1) into user_name, host_name;
  #!!! Костыль.
  select Host into host_name from mysql.user where User = user_name;
END;

sad

А как сделать не криво?
Не думаю, что сам подход надо менять. Проверять права высокого уровня в процедурах - вполне логично.


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#5 21.05.2010 15:47:37

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Поведение CURRENT_USER()

Даже в не-web-приложении не нужно смешивать smile

Вот тут Вам нужно определиться — либо Вам нужны высокоуровневые права, либо
низкоуровневые. Ваша проблема в том, что Вы не записали это на бумажке и не
поставили под этим подпись «так я буду делать, и никак иначе». Вы пытаетесь
сделать смесь высокоуровневого и низкоуровневого. И от этого страдаете.

Либо высокого уровня — независимые логины-пароли от БД — и тогда проверяете
в процедурах, либо низкого уровня — и тогда доверяете проверку прав MySQL.

Неактивен

 

#6 21.05.2010 16:08:13

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Поведение CURRENT_USER()

Вот тут Вам нужно определиться — либо Вам нужны высокоуровневые права, либо
низкоуровневые. Ваша проблема в том, что Вы не записали это на бумажке и не
поставили под этим подпись «так я буду делать, и никак иначе». Вы пытаетесь
сделать смесь высокоуровневого и низкоуровневого. И от этого страдаете.

Мне нужно и то, и это.

Либо высокого уровня — независимые логины-пароли от БД — и тогда проверяете
в процедурах, либо низкого уровня — и тогда доверяете проверку прав MySQL.

А как вы мне предлагаете делать запросы?
Ведь запросы бывают разные. Определить их список и упрятать в процедуры - ещё более извращённый вариант. Сложный и плохо расширяемый.
К тому же, зачем дублировать таблицу mysql.user в своей БД?

В чём минусы использования системных аккаунтов? Они нагружают систему?
Сложно администрируются? Загромождают БД?

Плюсов много. Хотя-бы встроенный механизм прав. К чему делать то, что уже реализовано?
Плюс, всё нормально работает, если не считать этой функции. Кстати, раньше её поведение было иное... Мда, "обратная совместимость". :-\


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#7 21.05.2010 16:46:49

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Поведение CURRENT_USER()

Хорошо, Вы решили использовать встроенную систему прав MySQL. Используйте ее.
Те, кто не может запускать процедуру — не могут ее запускать. Проверять внутри
ничего не надо. Если функция может выполнять два разных действия в зависимости
от того, есть ли у пользователя права, это должны быть две разные функции.

Неактивен

 

#8 21.05.2010 21:45:49

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Поведение CURRENT_USER()

Хорошо, Вы решили использовать встроенную систему прав MySQL. Используйте ее.
Те, кто не может запускать процедуру — не могут ее запускать. Проверять внутри
ничего не надо.

Да, я думал об этом. В принципе, переделать возможно. И достаточно просто.
У меня есть таблица с правами группы.
Вместо проверки прав группы в процедуре, добавить в триггер установку прав на запуск процедур.
Но, во-первых, это не решит проблему окончательно. Поскольку, ключи в таблице с пользовательской информацией - Host/User.
Например, пользователь меняет договор. Мне нужно занести ФИО в поле VARCHAR.
ФИО берётся из таблицы user_data, где ключ Host/User. Работать, очевидно, с таким поведением функции, это не будет.
Во-вторых, я не вижу в чём ущербность моего подхода? Есть ли что-то такое, что позволило бы мне уверенно сказать: "Нет. Так делать нельзя. Это абсолютно исключено."?

Если функция может выполнять два разных действия в зависимости
от того, есть ли у пользователя права, это должны быть две разные функции.

Я понимаю. Но вот, например, процедура добавляет договор.
Она проверяет права на добавление и изменение договора.
Если есть права на изменение, пропускается проверка дат.
Код процедуры немаленький. Стоит ли делать две процедуры, в таком случае?
Да, конечно, возможно сделать "накладку", которая будет проверять даты и отдельно на неё выдавать права.
Но стоит ли оно того? Ради чего?


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#9 24.05.2010 17:06:11

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Поведение CURRENT_USER()

Уху, я бы действительно не привязывался к правам MySQL smile

Неактивен

 

#10 24.05.2010 21:03:06

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Поведение CURRENT_USER()

Почему?


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#11 25.05.2010 20:37:52

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Поведение CURRENT_USER()

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

Неактивен

 

#12 26.05.2010 17:24:33

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Поведение CURRENT_USER()

Но, в таком случае, мне придётся делать свою реализацию работы с пользователями.
Почти аналогичную сделанной в MySQL.
А для чего? Что плохо сейчас?

Отредактированно Артём Н. (26.05.2010 17:27:24)


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#13 27.05.2010 01:20:05

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Поведение CURRENT_USER()

Плохо то, что встроенная Вас не устраивает, а другую Вы писать не хотите —
вот и мучаетесь, не зная, как поступить smile

В любом случае, это вопрос предпочтений. Предлагаю тему закрыть, т.к. она
перестала нести полезную нагрузку приблизительно после первого ответа smile

Неактивен

 

#14 27.05.2010 10:58:54

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Поведение CURRENT_USER()

Плохо то, что встроенная Вас не устраивает, а другую Вы писать не хотите —
вот и мучаетесь, не зная, как поступить

Угу. sad
Встроенную я использую только для:
1.) Идентификации и авторизации пользователей.
2.) Полного запрета записи в БД.
3.) Ну ещё права на справочники некоторым даю.
Чтобы логику клиента сильнее не усложнять.

А все остальные права - "высокоуровневые". Чем же плоха такая организация?
Помимо, одной функции, которая работает не так, как я предполагал?
Я не могу понять.

В любом случае, это вопрос предпочтений. Предлагаю тему закрыть, т.к. она
перестала нести полезную нагрузку приблизительно после первого ответа

Вы ошибаетесь. Сейчас я решаю стоит переделывать или нет. smile


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#15 27.05.2010 14:55:22

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Поведение CURRENT_USER()

Ну, что-то переделывать прийдется безусловно, т.к. функция для Вас
не работает, и альтернативы нету sad

Неактивен

 

#16 27.05.2010 16:10:30

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Поведение CURRENT_USER()

Код:

#!!! Костыль.
select Host into host_name from mysql.user where User = user_name;

Что плохого в такой схеме если, теоретически, удалось с успехом избавиться от костыля?


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#17 30.05.2010 13:35:17

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Поведение CURRENT_USER()

Можете мне ответить на следующую три вопроса:
1. Какие у меня могут быть конкретные проблемы, при такой организации прав,
которая у меня сейчас?
2. Какие могут быть проблемы, при использовании прав на процедуры?
3. В чём лучше и в чём хуже второе первого?


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#18 30.05.2010 13:52:51

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Поведение CURRENT_USER()

Хм... Хотя, сейчас столкнулся с проблемами, при создании временных таблиц...
Думаю, что есть смысл в правах на процедуры...
Но, помимо этого?

Отредактированно Артём Н. (30.05.2010 16:08:21)


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#19 31.05.2010 19:39:10

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Поведение CURRENT_USER()

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

Неактивен

 

#20 01.06.2010 21:11:18

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Поведение CURRENT_USER()

Учитывая то, что поддерживать придётся, скорее всего, мне - у меня...
Ну, в таком случае, есть два варианта:
1. Использовать стандартный механизм управления пользователями и права на выполнение процедур.
2. Реализовать сходный со стандартным механизм.

В первом - минусы:
1. Связка со стандартным механизмом (мне надо ещё хранить доп. данные пользователя, к примеру, ФИО).
Т.е. не решается проблема с этой функцией.
2. Права на процедуры. Их, наверное, сложнее администрировать. Права на выполнение неочевидны.
3. Большое число пользовательских аккаунтов в СУБД.

Во втором минусы:
1. Самостоятельная реализация механизма.
2. Низкая гибкость, по сравнению со стандартным.
К примеру, стандартный механизм может реализовывать ограничения по ресурсам (ну, может когда-то будет, я на это надеюсь). А реализовать это самостоятельно - задача уже нетривиальная и плохо разрешимая.

Так как лучше сделать, в моём случае?


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#21 02.06.2010 00:06:28

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Поведение CURRENT_USER()

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

Поэтому права - либо на уровне встроенного механизма MySQL (процедуры можно делать с SQL_SECURITY INVOKER), либо вообще на приложении-клиенте.

Кстати (спрашиваю чисто ради интереса). Зачем Вам вообще столько кода в MySQL? (Просто единственный широко известный случай, когда использование хранимой процедуры оправдано - это разбор денормализованной таблицы курсором; и то только ради скорости).

Неактивен

 

#22 02.06.2010 17:06:15

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Поведение CURRENT_USER()

Поэтому права - либо на уровне встроенного механизма MySQL (процедуры можно делать с SQL_SECURITY INVOKER)

Тогда придётся устанавливать права на таблицы. К примеру, в этом случае, нельзя проверить даты и, вообще, любые вводимые данные.
Или ограничить доступ только определёнными строками.

либо вообще на приложении-клиенте.

o.O Это точно - не вариант. Получается, что каждый может делать всё, что захочет.

Кстати (спрашиваю чисто ради интереса). Зачем Вам вообще столько кода в MySQL? (Просто единственный широко известный случай, когда использование хранимой процедуры оправдано - это разбор денормализованной таблицы курсором; и то только ради скорости).

Ну, во-первых, нужно многопользовательское приложение.
То, что было до этого, мне не понравилось.
Логины/пароли хранились в своей таблице, незашифрованными.
Каждому открыт доступ. Привилегии всем даны. Короче, сплошная "демократия".
Плюс, работа через ODBC. И клиент на том же разделе (причём расшаренном), что и БД. Все заходили в клиент под администратором.
Я решил такую халтуру не делать, а сделать, более ли менее нормально.
Во-вторых, требования слегка изменились. Пользователям всё позапрещать.
Даты проверять на проставление "задним числом". Действия протоколировать.
(Ещё и откат делать, но, нафиг, основное-то сделать бы).
В-третьих, спрашивали про "второй офис" и про web-интерфейс. На будущее.
А, если есть централизованная БД...
К тому же, в случае с web-интерфейсом, зачем ограничивать работу только им и всё делать с нуля? Пусть и клиенты с той же БД работают...

В общем, я подумал и решил сделать клиент потоньше, а сервер потолще...
Разве это плохо - переложить всё на сервер?


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

#23 02.06.2010 18:16:27

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Поведение CURRENT_USER()

Разве это плохо - переложить всё на сервер?

Да нет, не плохо.. Просто на SQL писать замучаетесь. Прокладку бы Вам какую-нибудь на сервере.. (в смысле, чтоб не голый MySQL). Но это уже Вам виднее.

Зато будете редким человеком, кто отважился логику приложения реализовывать на MySQL smile

Неактивен

 

#24 02.06.2010 20:44:10

Артём Н.
Активист
Зарегистрирован: 03.11.2009
Сообщений: 156

Re: Поведение CURRENT_USER()

Да нет, не плохо.. Просто на SQL писать замучаетесь. Прокладку бы Вам какую-нибудь на сервере.. (в смысле, чтоб не голый MySQL). Но это уже Вам виднее.

Думал. Решил отказаться. Для "прокладки" нужно думать о протоколе.
И ещё проблем больше.

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

Мне нужно это читать, как "редкий дурак"? smile
Вообще, у меня не ахти какое сложное приложение.
Вышло всего-лишь на ~3500 строк. И я не единственный, кто делает логику на SQL.
К тому же, тот SQL, это обычный, Тьюринг-полный язык. Что такого?
Меня больше волнует клиент, а не сервер.
С сервером уже почти все проблемы решены.

Кстати, думаю, что авторизацию реализовать, "как в MySQL" не очень сложно.
Только, наверное, это будет изобретением велосипеда.

Насчёт, связки со стандартным механизмом я думал.
У меня в ключ входит Host. А нафиг мне Host, в принципе?


"И ни птица, ни ива слезы не прольет,
Если сгинет с земли человеческий род.
И весна, и весна встретит новый рассвет,
Не заметив, что нас уже нет..."

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson