পোস্টগ্রিএসকিউএল (বা সাধারণভাবে এসকিউএল) এ ব্যবসায়ের লজিক অনুমতিগুলি কীভাবে প্রয়োগ করা যায়?


16

ধরা যাক আমার কাছে আইটেমের একটি টেবিল রয়েছে:

CREATE TABLE items
(
    item serial PRIMARY KEY,
    ...
);

এখন আমি প্রতিটি আইটেমের জন্য "অনুমতি" (দয়া করে মনে রাখবেন, আমি ধারণা পরিচয় করিয়ে দিতে চাই না এখানে ডাটাবেসের অ্যাক্সেস অনুমতি বিষয়ে কথা, কিন্তু বিজনেস লজিক অনুমতি ঐ আইটেমটির জন্য)। প্রতিটি আইটেমের ডিফল্ট অনুমতি এবং প্রতি ব্যবহারকারী অনুমতি যা ডিফল্ট অনুমতিগুলি ওভাররাইড করতে পারে has

আমি এটিকে বাস্তবায়নের বিভিন্ন উপায় সম্পর্কে চিন্তা করার চেষ্টা করেছি এবং নিম্নলিখিত সমাধানগুলি নিয়ে এসেছি, তবে আমি নিশ্চিত নই যে কোনটি সর্বোত্তম এবং কেন:

1) বুলিয়ান সমাধান

প্রতিটি অনুমতি জন্য একটি বুলিয়ান কলাম ব্যবহার করুন:

CREATE TABLE items
(
    item serial PRIMARY KEY,

    can_change_description boolean NOT NULL,
    can_change_price boolean NOT NULL,
    can_delete_item_from_store boolean NOT NULL,
    ...
);

CREATE TABLE item_per_user_permissions
(
    item int NOT NULL REFERENCES items(item),
    user int NOT NULL REFERENCES users(user),

    PRIMARY KEY(item, user),

    can_change_description boolean NOT NULL,
    can_change_price boolean NOT NULL,
    can_delete_item_from_store boolean NOT NULL,
    ...
);

সুবিধা : প্রতিটি অনুমতি নামকরণ করা হয়।

অসুবিধাগুলি : এমন কয়েক ডজন অনুমতি রয়েছে যা কলামগুলির সংখ্যা উল্লেখযোগ্যভাবে বৃদ্ধি করে এবং আপনি সেগুলি দুবার সংজ্ঞা দিতে হবে (প্রতিটি টেবিলে একবার)।

2) পূর্ণসংখ্যা সমাধান

একটি পূর্ণসংখ্যা ব্যবহার করুন এবং এটি একটি বিটফিল্ড হিসাবে বিবেচনা করুন (যেমন বিট 0 এর জন্য can_change_description, বিট 1 এর জন্য can_change_price, এবং আরও কিছু, এবং অনুমতিগুলি সেট করতে বা পড়তে বিটওয়াইজ অপারেশনগুলি ব্যবহার করুন)।

CREATE DOMAIN permissions AS integer;

সুবিধা : খুব দ্রুত।

অসুবিধাগুলি : আপনাকে ডাটাবেস এবং ফ্রন্ট-এন্ড ইন্টারফেস উভয় ক্ষেত্রে কোন বিটের জন্য কোন বিট দাঁড়ায় তা ট্র্যাক করে রাখতে হবে।

3) বিটফিল্ড সমাধান

একই হিসাবে 2), কিন্তু ব্যবহার bit(n)। সম্ভবত একই সুবিধা এবং অসুবিধাগুলি, সম্ভবত কিছুটা ধীর।

4) এনাম সলিউশন

অনুমতিগুলির জন্য একটি এনাম টাইপ ব্যবহার করুন:

CREATE TYPE permission AS ENUM ('can_change_description', 'can_change_price', .....);

এবং তারপরে ডিফল্ট অনুমতিগুলির জন্য একটি অতিরিক্ত টেবিল তৈরি করুন:

CREATE TABLE item_default_permissions
(
    item int NOT NULL REFERENCES items(item),
    perm permission NOT NULL,

    PRIMARY KEY(item, perm)
);

এবং প্রতি ব্যবহারকারী সংজ্ঞা টেবিল এ পরিবর্তন করুন:

CREATE TABLE item_per_user_permissions
(
    item int NOT NULL REFERENCES items(item),
    user int NOT NULL REFERENCES users(user),
    perm permission NOT NULL,

    PRIMARY KEY(item, user, perm)    
);

সুবিধা : পৃথক অনুমতিগুলির নামকরণ করা সহজ (আপনার বিট পজিশন পরিচালনা করতে হবে না)।

অসুবিধাগুলি : কেবলমাত্র ডিফল্ট অনুমতিগুলি পুনরুদ্ধার করার জন্য, এর জন্য দুটি অতিরিক্ত টেবিল অ্যাক্সেস করা দরকার: প্রথমত, ডিফল্ট অনুমতিগুলির সারণী এবং দ্বিতীয়টি, এনাম মানগুলি সংরক্ষণ করে সিস্টেম ক্যাটালগ।

বিশেষত যেহেতু ডিফল্ট অনুমতিগুলি অবশ্যই সেই আইটেমটির প্রতিটি একক পৃষ্ঠাগুলির জন্য পুনরুদ্ধার করতে হবে , শেষ বিকল্পটির কার্যকারিতা প্রভাবটি উল্লেখযোগ্য হতে পারে।

5) এনাম অ্যারে সমাধান

4 হিসাবে একই) তবে সমস্ত (ডিফল্ট) অনুমতি ধরে রাখতে একটি অ্যারে ব্যবহার করুন:

CREATE TYPE permission AS ENUM ('can_change_description', 'can_change_price', .....);

CREATE TABLE items
(
    item serial PRIMARY KEY,

    granted_permissions permission ARRAY,
    ...
);

সুবিধা : পৃথক অনুমতিগুলির নামকরণ করা সহজ (আপনার বিট পজিশন পরিচালনা করতে হবে না)।

অসুবিধাগুলি : 1 ম সাধারণ ফর্মটি ভঙ্গ করে এবং কিছুটা কুৎসিত। অনুমতিগুলির সংখ্যা বৃহত্তর হলে (প্রায় 50) এক সারিতে যথেষ্ট পরিমাণে বাইট নেয়।

আপনি কি অন্যান্য বিকল্পের কথা ভাবতে পারেন?

কোন পন্থা গ্রহণ করা উচিত এবং কেন?

দয়া করে মনে রাখবেন: এটি স্ট্যাকওভারফ্লোতে পোস্ট করা একটি প্রশ্নের একটি সংশোধিত সংস্করণ ।


2
কয়েক ডজন বিভিন্ন অনুমতি নিয়ে আমি একটি (বা তারও বেশি) bigintক্ষেত্রগুলি বেছে নিতে পারি (প্রতিটি 64 টি বিটের জন্য ভাল) বা কিছুটা স্ট্রিং। আমি এসও-তে সম্পর্কিত
এরউইন ব্র্যান্ডসটেটার

উত্তর:


7

আমি জানি যে আপনি প্রতি সেটে ডাটাবেস সুরক্ষা সম্পর্কে জিজ্ঞাসা করছেন না , তবে আপনি ডাটাবেস সুরক্ষা ব্যবহার করে যা করতে চান তা করতে পারেন। এমনকি আপনি এটি কোনও ওয়েব অ্যাপ্লিকেশনটিতেও ব্যবহার করতে পারেন। আপনি যদি ডাটাবেস সুরক্ষা ব্যবহার করতে না চান, তবে স্কিমগুলি এখনও প্রয়োগ হয়।

আপনি কলাম-স্তরের সুরক্ষা, সারি-স্তরের সুরক্ষা এবং সম্ভবত শ্রেণিবদ্ধ ভূমিকা পরিচালনা করতে চান। ভূমিকা-ভিত্তিক সুরক্ষার ব্যবহারকারীর উপর ভিত্তি করে সুরক্ষার চেয়ে পরিচালনা করা অনেক সহজ।

এই উদাহরণ কোডটি পোস্টগ্রেএসকিউএল 9.4 এর জন্য যা শীঘ্রই প্রকাশিত হবে। আপনি এটি 9.3 দিয়ে করতে পারেন, তবে এখানে আরও ম্যানুয়াল শ্রম প্রয়োজন।

আপনি যদি পারফরম্যান্সের সাথে সম্পর্কিত হন - তবে আপনার যা হওয়া উচিত তা সবকিছু সূচিযোগ্য হতে চান। এর অর্থ হ'ল বিট-মাস্ক এবং অ্যারে ক্ষেত্রগুলি সম্ভবত ভাল ধারণা হবে না।

এই উদাহরণে, আমরা dataস্কিমাতে মূল ডেটা টেবিলগুলি এবং এর সাথে সম্পর্কিত মতামত রাখি public

create schema data; --main data tables
create schema security; --acls, security triggers, default privileges

create table data.thing (
  thing_id int primary key,
  subject text not null, --or whatever
  owner name not null
);

ডেটাতে একটি ট্রিগার রাখুন inোকানো এবং আপডেটগুলি প্রয়োগের জন্য যা মালিকের কলামটি কারেন্ট_ইউসার। সম্ভবত কেবলমাত্র মালিককে তার নিজস্ব রেকর্ডস (অন্য ট্রিগার) মুছতে অনুমতি দিন।

একটি WITH CHECK OPTIONদৃশ্য তৈরি করুন যা ব্যবহারকারীরা আসলে ব্যবহার করবে। এটিকে আপডেটযোগ্য করে তোলার জন্য সত্যিই কঠোর চেষ্টা করুন, অন্যথায় আপনার ট্রিগার / বিধিগুলির প্রয়োজন হবে যা আরও কাজ।

create view public.thing with(security_barrier) as 
select
thing_id,
subject,
owner,
from data.thing
where
pg_has_role(owner, 'member') --only owner or roles "above" him can view his rows. 
WITH CHECK OPTION;

এর পরে, একটি অ্যাক্সেস-নিয়ন্ত্রণের তালিকা টেবিল তৈরি করুন:

--privileges r=read, w=write

create table security.thing_acl (
  thing_id int,
  grantee name, --the role to whom your are granting the privilege
  privilege char(1) check (privilege in ('r','w') ),

  primary key (thing_id, grantee, privilege),

  foreign key (thing_id) references data.thing(thing_id) on delete cascade
);

আপনার দৃষ্টিভঙ্গি ACL এর অ্যাকাউন্টে পরিবর্তন করুন:

drop view public.thing;

create view public.thing with(security_barrier) as 
select
thing_id,
subject,
owner
from data.thing a
where
pg_has_role(owner, 'member')
or exists (select 1 from security.thing_acl b where b.thing_id = a.thing_id and pg_has_role(grantee, 'member') and privilege='r')
with check option;

একটি ডিফল্ট সারি সুবিধার টেবিল তৈরি করুন:

create table security.default_row_privileges (
  table_name name,
  role_name name,
  privilege char(1),

  primary key (table_name, role_name, privilege)
);

ডেটা.ইটিং-এ onোকানোর জন্য একটি ট্রিগার রাখুন যাতে এটি ডিফল্ট সারি সুবিধাগুলি অনুলিপিকে সংরক্ষণ করে thing

  • টেবিল-স্তরের সুরক্ষা যথাযথভাবে সামঞ্জস্য করুন (অযাচিত ব্যবহারকারীদের থেকে প্রবেশ প্রতিরোধ করুন)। কেউই ডেটা বা সুরক্ষা স্কিমা পড়তে সক্ষম হবে না।
  • কলাম-স্তরের সুরক্ষা যথাযথভাবে সামঞ্জস্য করুন (কিছু ব্যবহারকারীকে কিছু কলাম দেখতে / সম্পাদনা করা থেকে বিরত করুন)। কোনও ব্যবহারকারী কোনও কলাম দেখতে পাচ্ছেন তা পরীক্ষা করতে আপনি has_column_privilege () ব্যবহার করতে পারেন।
  • সম্ভবত আপনার দৃষ্টিতে সুরক্ষার সুনির্দিষ্ট ট্যাগটি চান।
  • কারা এই সুযোগসুবিধা দিয়েছে এবং ট্রানজিস্টরা সেই সারিটিতে সুবিধাগুলি পরিচালনা করতে পারে কিনা তা ট্র্যাক করতে এসিএল টেবিলগুলিতে যুক্ত grantorএবং admin_optionকলামগুলি বিবেচনা করুন ।
  • পরীক্ষার প্রচুর

This এই ক্ষেত্রে পিজি_হ্যাস_রোল সম্ভবত ইনডেক্সযোগ্য নয়। আপনাকে বর্তমানের_উসারের সাথে সমস্ত উচ্চতর ভূমিকার একটি তালিকা পেতে হবে এবং তার পরিবর্তে মালিক / মঞ্জুরির মানের সাথে তুলনা করতে হবে।


" আমি এখানে ডাটাবেস অ্যাক্সেস অনুমতিগুলির বিষয়ে কথা বলছি না " অংশটি দেখেছেন ?
a_horse_with_no_name

@ এ_ ঘোড়া_বিহীন_নাম_হ্যাঁ হ্যাঁ আমি করেছি। তিনি তার নিজের আরএলএস / এসিএল সিস্টেমটি লিখতে পারেন , বা তিনি যা চাইছেন তা করতে তিনি একটি ডাটাবেসের অন্তর্নির্মিত সুরক্ষা ব্যবহার করতে পারেন।
নীল ম্যাকগুইগান

আপনার বিস্তারিত উত্তরের জন্য ধন্যবাদ! তবে আমি মনে করি না যে এখানে ডাটাবেস রোলগুলি ব্যবহার করা সঠিক উত্তর কারণ কেবল কর্মীরাই নয়, তবে প্রতিটি একক ব্যবহারকারীরও অনুমতি থাকতে পারে। উদাহরণগুলি হ'ল 'ক্যান_ভিউ_আইটিম', 'ক্যান_বুলক_অর্ডার_াইটেম' বা 'ক্যান_রভিউ_াইটেম'। আমি মনে করি আমার অনুমতি নামগুলির আসল পছন্দ আপনাকে বিশ্বাস করতে পরিচালিত করেছিল যে এটি কেবল কর্মীদের অনুমতি সম্পর্কে, তবে এই সমস্ত নামই জটিলতাগুলি বিমোচন করার উদাহরণ মাত্র। যেমন আমি মূল প্রশ্নে বলেছি, এটি প্রতি ব্যবহারকারীর অনুমতি সম্পর্কে নয়, স্টাফের অনুমতি অনুযায়ী নয় ।
জনক্যান্ড

যাইহোক, ব্যবহারকারীদের সারণীতে প্রতিটি ব্যবহারকারীর সারির জন্য পৃথক ডাটাবেসের ভূমিকা থাকতে পারে বলে মনে হয় যে ওভারকিল এবং খুব সহজেই পরিচালনা করা যায়। তবে আমি মনে করি যে আপনার উত্তরটি বিকাশকারীদের কেবলমাত্র কর্মীদের অনুমতি প্রয়োগের জন্য মূল্যবান।
জনক্যান্ড

1
@ জনক্যান্ড আমি অন্য কোথাও অনুমতিগুলি পরিচালনা করা কতটা সহজ এটি সত্যই দেখতে পাচ্ছি না, তবে আপনি একবার এটির সমাধান হয়ে গেলে আপনার সমাধানের দিকে নির্দেশ করুন! :)
নীল ম্যাকগুইগান

4

আপনি কি অ্যাক্সেস নিয়ন্ত্রণ তালিকা পোস্টগ্রিএসকিউএল এক্সটেনশনটি ব্যবহারের কথা বিবেচনা করেছেন ?

এটিতে দেশীয় পোস্টগ্র্যাসকিউসিএল ডেটা টাইপ এসিই এবং ফাংশনগুলির একটি সেট রয়েছে যা আপনাকে কোনও ব্যবহারকারীকে ডেটা অ্যাক্সেস করার অনুমতি দেয় কিনা তা খতিয়ে দেখার অনুমতি দেয়। এটি পোস্টগ্রিসএসকিউএল রোলস সিস্টেমের সাথে বা আপনার অ্যাপ্লিকেশন ব্যবহারকারী / ভূমিকা আইডি উপস্থাপনকারী বিমূর্ত সংখ্যা (বা ইউইউডি) সহ কাজ করে।

আপনার ক্ষেত্রে, আপনি কেবলমাত্র আপনার ডেটা টেবিলগুলিতে একটি এসিএল কলাম যুক্ত করেছেন এবং acl_check_accessকোনও এসিএলের বিরুদ্ধে কোনও ব্যবহারকারীকে পরীক্ষা করতে একটি ফাংশন ব্যবহার করেন ।

CREATE TABLE items
(
    item serial PRIMARY KEY,
    acl ace[],
    ...
);

INSERT INTO items(acl, ...) VALUES ('{a//<user id>=r, a//<role id>=rwd, ...}');

SELECT * FROM items where acl_check_access(acl, 'r', <roles of the user>, false) = 'r'

ব্যবসায়ের লজিক অনুমতি নিয়ে কাজ করার জন্য এসিএলগুলি ব্যবহার করা একটি অত্যন্ত নমনীয় উপায়। তদাতিরিক্ত, এটি অবিশ্বাস্যরূপে দ্রুত - গড় ওভারহেড একটি রেকর্ড পড়ার জন্য প্রয়োজনীয় সময়ের 25% থাকে। একমাত্র সীমাবদ্ধতা হ'ল এটি প্রতি বস্তু প্রকারে সর্বোচ্চ 16 টি কাস্টম অনুমতি সমর্থন করে supports


1

আমি এটিকে এনকোড করার আরও একটি সম্ভাবনা ভাবতে পারি, এটি সম্পর্কিত

আপনার যদি permission_per_itemটেবিলের প্রয়োজন না হয় তবে আপনি এড়িয়ে যেতে পারেন Permissionsএবং Itemsসরাসরি item_per_user_permissionsটেবিলের সাথে সংযোগ স্থাপন করতে পারেন ।

এখানে চিত্র বর্ণনা লিখুন

কিংবদন্তি
চিত্র

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.