Yii Framework Forum: Uwierzytelniony widzi jedynie swoje dane (posty, newsy, userów) - Yii Framework Forum

Jump to content

  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

Uwierzytelniony widzi jedynie swoje dane (posty, newsy, userów) Rate Topic: -----

#1 User is offline   belzi 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 4
  • Joined: 18-February 12

Posted 18 February 2012 - 05:38 AM

Witam. To mój pierwszy post na forum.

Od kilku tygodni przyglądam się Yii i bardzo mi się spodobał.
Przeszedłem przez lekturę 'Przewodnika' i 'zaimplementowałem' bloga ;-)

W ramach dalszej nauki chciałbym dać możliwość 'zakładania' bloga wielu
użytkownikom w ramach tej samej aplikacji, wiec np. każdy po pomyślnym
uwierzytelnieniu widziałby np. jedynie swoje posty. Jednak napotkałem na problem. Jak łatwo zdeterminować jakie
dane mogę danemu, uwierzytelnionemu użytkownikowi pokazać?

Sam gii generuje nam wiele plikow i faktycznie aplikacja 'dziala' niemal od
razu. Gdy wpisze url /post/1 otrzymam dane posta 1, jak 2 to dane posta 2 itp.

Gdy wpisze samo /post dostane liste postow - ale wszystkich!

W kontrolerze pobierającym dane moge ograniczyc dane do np. user_id===Yii::app()->user->id,
ale skolei tych akcji kontrolera też jest niemało, więc
zmiana tego w każdym miejscu jest niewygodna. Inna rzecz, że nawet jak
powyrzucam z widoku linki do tych akcji, ktoś znający budowę standardowej
aplikacji w yii, może zacząć 'preparować' linki - i co wtedy?

Więc jak uniemożliwić podejrzenie posta o ID=2 osobie, która nie jest jego
autorem?

Jak to ugryźć?
Najchętniej bym filtrował dane już na poziomie samego modelu tak żeby
odwołując się do niego z akcji kontrolera miał pewność, że ograniczy mi
serwowane dane do tych przypisanych danemu użytkownikowi.

Czytałem już trochę o 'scopes', 'filtrach' i 'behaviors', ale nie wiem jeszcze
jak się do nich zabrać i które rozwiązanie jest najlepsze.
A jakie Wy stosujecie?

Kolejny bardziej złożony przypadek (bardziej mnie interesuje) to np.
osoba przypisana do danego wydziału (department) np. na uczelni. Wydział oferuje nauke na
wielu kierunkach, zatrudnia wielu pracowników i zrzesza wielu studentów itd.

Załóżmy, że do 'panelu' loguje się taki pracownik. Na podstawie jego ID chcemy
odczytać do jakiego wydziału jest przypisany (department_id), chcemy mu wylistować pracowników
w tym wydziale itd.

Jak najlepiej zrealizować coś takiego? Po uwierzytelnieniu znamy ID
użytkownika. Po relacji (deparment_id) możemy odczytać do jakiego wydziału
jest przypisany itd. Jak realizując pobieranie danych zabezpieczyć się przed
'preparowaniem' linków - tak żeby mieć pewność, że zalogowany zobaczy jedynie
te dane, które powinien?

Trochę się rozpisałem.. ale chciałem mieć pewność, że dobrze opiszę istote
problemu. Za wszelkie sugestie, rozwiązania, liki z góry dziękuję.
0

#2 User is offline   sidewinder 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 218
  • Joined: 08-July 09
  • Location:Poland

Posted 18 February 2012 - 08:37 AM

Witam,
nie mam w tej chwili za dużo czasu (za 15 minut start 10km klasykiem ;) ), ale postaram się rozwinąć temat później. Mówiąc krótko, zapoznaj się z RBAC.
Koniecznie przeczytaj:
dział o autoryzacji w podręczniku Yii: http://www.yiiframew.../en/topics.auth a szczególnie od punktu 6.
wpis na wiki yii: http://www.yiiframew...cal-rbac-scheme.
wpis na wikipedii: http://en.wikipedia...._access_control

W podręczniku yii zwróć uwagę na reguły biznesowe, bo kilkoma prostymi testami logicznymi możesz odwalić kawał dobrej roboty i ułatwić sobie życie.

Uważam się za osobę o przeciętnej inteligencji, a czytać to wszystko musiałem kilka razy, żeby do mnie dotarło w 100% jak działa RBAC. W razie czego więc nie zniechęcaj się i czytaj raz jeszcze:).
---------------------------------------------------------------------
"Never memorize what you can look up in books."
Albert Einstein
0

#3 User is offline   drylko 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 86
  • Joined: 13-September 09
  • Location:Poland

Posted 18 February 2012 - 08:52 AM

View Postbelzi, on 18 February 2012 - 05:38 AM, said:

W ramach dalszej nauki chciałbym dać możliwość 'zakładania' bloga wielu
użytkownikom w ramach tej samej aplikacji, wiec np. każdy po pomyślnym
uwierzytelnieniu widziałby np. jedynie swoje posty. Jednak napotkałem na problem. Jak łatwo zdeterminować jakie
dane mogę danemu, uwierzytelnionemu użytkownikowi pokazać?
(...)
Więc jak uniemożliwić podejrzenie posta o ID=2 osobie, która nie jest jego
autorem?

Jak to ugryźć?
Najchętniej bym filtrował dane już na poziomie samego modelu tak żeby
odwołując się do niego z akcji kontrolera miał pewność, że ograniczy mi
serwowane dane do tych przypisanych danemu użytkownikowi.

Czytałem już trochę o 'scopes', 'filtrach' i 'behaviors', ale nie wiem jeszcze
jak się do nich zabrać i które rozwiązanie jest najlepsze.
A jakie Wy stosujecie?

Cześć,
jeśli blog jest prywatny i posty w nim ma widzieć tylko właściciel, to do każdego wybierania z bazy dodaj ograniczenie dla konkretnego author_id (czy jak tam się nazywa kolumna w bazie). Możesz to zrobić za pomocą 'scopes',np. tak:
class Post extends CActiveRecord
{
    ......
    public function scopes()
    {
        return array(
            'own'=>array(
                'condition'=>'author_id='.Yii::app()->getUser()->getId(),
            ),
        );
    }
}
Post::model()->own()->findAll();
$model=Post::model()->findByPk(2); // zwróci post o pk=2, author_id nie ma znaczenia
$model=Post::model()->own()->findByPk(2); // zwróci null, jeśli author_id != Yii::app()->getUser()->getId()

jeśli każdy może przeglądać wszystkie blogi i chcesz wyświetlać tylko posty właścicieli, to Twój url musi zawierać informację o użytkowniku, którego blog jest aktualnie przeglądany (http://www.yiiframew...amed-parameters), np. jego username, albo id. Wtedy korzystasz z np. innego scope'a z parametrem:
class Post extends CActiveRecord
{
    ......
    public function author($id)
    {
        $this->getDbCriteria()->mergeWith(array(
            'condition'=>'author_id='.$id,
        ));
        return $this;
    }
}
Post::model()->author(2)->findAll(); // wszystkie posty autora o id=2
$model=Post::model()->author(2)->findByPk(2); // zwróci post o pk=2, jeśli autorem jest user o id=2, bądź null w przeciwnym wypadku


View Postbelzi, on 18 February 2012 - 05:38 AM, said:

Kolejny bardziej złożony przypadek (bardziej mnie interesuje) to np.
osoba przypisana do danego wydziału (department) np. na uczelni. Wydział oferuje nauke na
wielu kierunkach, zatrudnia wielu pracowników i zrzesza wielu studentów itd.

Załóżmy, że do 'panelu' loguje się taki pracownik. Na podstawie jego ID chcemy
odczytać do jakiego wydziału jest przypisany (department_id), chcemy mu wylistować pracowników
w tym wydziale itd.

Jak najlepiej zrealizować coś takiego? Po uwierzytelnieniu znamy ID
użytkownika. Po relacji (deparment_id) możemy odczytać do jakiego wydziału
jest przypisany itd. Jak realizując pobieranie danych zabezpieczyć się przed
'preparowaniem' linków - tak żeby mieć pewność, że zalogowany zobaczy jedynie
te dane, które powinien?

To samo, co wyżej.

d
0

#4 User is offline   belzi 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 4
  • Joined: 18-February 12

Posted 18 February 2012 - 11:13 AM

Witam.

Cieszę się tak szybkiego odzewu. Dziękuję za sugestie i rozwiązania. RBAC'em się zainteresuję. Czytałem o nim wcześniej. Implementowałem ACL'a w Zendzie, a to wydaje mi się podobne, więc nie powinno być problemu. Dzięki za sugestię!

Co do scopów to fajnie, że są i tak jak podejrzewałem łatwo je można zaadoptować jako rozwiązanie opisanego przeze mnie problemu, jednak, może to zabrzmi naiwnie, spodziewałem się (oczekiwałem) czegoś innego. Dlaczego? Dlatego, że aby użyć tych zdefiniowanych scopów i tak muszę we wszystkich miejscach w kontrolerach czy w klasach innych modeli wymusić użycie scope'a, a to już jest błędogenne (gii wygenerował mi ileś tam odwołań do postów - teraz muszę odszukiwać każde z nich i wpisywać czy author czy nie author?).

Spodziewam się, że bez mojej implementacji się nie obejdzie jednak zanim w yii zaczne pisać coś większego niż blog wolałbym znać odpowiedź na większość nasuwających się wątpliwości.
Dziękuję raz jeszcze za odpowiedzi i liczę na kolejne. ;-)

Pozdrawiam.


edit.

Teraz w sumie pomyślałem, że to bardziej akcje kontrolerów wygenerowane przez gii mnie tak stresują. Gdybym utworzyl na ich bazie swoje np. /user/profile zamiast /user/view/ID, a takie akcje jak search czy admin zaremował, to wiele by mi to pomogło.

This post has been edited by belzi: 18 February 2012 - 11:24 AM

0

#5 User is offline   drylko 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 86
  • Joined: 13-September 09
  • Location:Poland

Posted 18 February 2012 - 02:37 PM

Cześć,

to tylko framework, a scaffolding nie zrobi za Ciebie gotowego projektu. Jednak jest jeszcze jeden rodzaj scope'ów: http://www.yiiframew...r#default-scope, więc może to rozwiąże Twój problem modyfikacji kodu w każdej akcji, która tego wymaga.
Jeśli chcesz, by Gii za każdym razem tworzyło szablon z jakiego chciałbyś korzystać rzuć okiem na ten temat: http://www.yiiframew...i#extending-gii

d
0

#6 User is offline   belzi 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 4
  • Joined: 18-February 12

Posted 19 February 2012 - 04:59 AM

View Postdrylko, on 18 February 2012 - 02:37 PM, said:

Cześć,

to tylko framework, a scaffolding nie zrobi za Ciebie gotowego projektu. Jednak jest jeszcze jeden rodzaj scope'ów: http://www.yiiframew...r#default-scope, więc może to rozwiąże Twój problem modyfikacji kodu w każdej akcji, która tego wymaga.
Jeśli chcesz, by Gii za każdym razem tworzyło szablon z jakiego chciałbyś korzystać rzuć okiem na ten temat: http://www.yiiframew...i#extending-gii

d


Witaj!
I to jest właściwa odpowiedź! Wczoraj już wyłączyłem komputer, ale niedługo po tym olśniło mnie, że przecież czytałem o czymś takim jak default scope's, i pewnie tego spróbuję!
Ważniejsze jest jednak to co napisałeś na samym początku - scaffolding nie zrobi za mnie projektu. Faktycznie zachłysnąłem się 'gotowością' wygenerowanej przez gii aplikacji. Pocieszające jest to, że niewielkim kosztem można to dostosować do swoich potrzeb.Dopiero po pewnym czasie zdałem sobie sprawę, że ja tak naprawdę wiem jak zrealizować to zadanie, a bardziej skupiłem się nad 'dostosowaniem' akcji wygenerowanych przez gii. Przy okazji natknąłem się na (krytyczny?) artykuł dotyczący gii:

weavora.com/blog/2012/02/11/scaffolding-in-yii-thoughts-about-gii

Jeszcze jedno pytanie pośrednio związane z moim problemem. Czy Waszym zdaniem bezpiecznie i wydajnie jest aby w klasie WebUser zapisać przez $this->setState np. wspomniany przeze mnie departmentId (zalogowany użytkownik przypisany jest do konkretnego wydziału)? W aplikacji będzie wiele rzeczy połączonych właśnie przez deparmentID. Czy lepiej jest zapamiętać jedynie user->id a później już w aplikacji normalnie User::model()->findByPk(ID)->department->id?

I co myślicie o zastosowaniu metody model w klasie WebUser?
public function getModel() 
{
    $user = $this->loadUser(Yii::app()->user->id);
    return $user;
}

protected function loadUser($id=null)
{
    if($this->_model===null)
    {
        if($id!==null)
            $this->_model=User::model()->findByPk($id);
    }
    return $this->_model;
}


Dzięki czemu wywołujemy jedynie przez:

Yii::app()->user->model->department->id;

Pozdrawiam.
0

#7 User is offline   drylko 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 86
  • Joined: 13-September 09
  • Location:Poland

Posted 20 February 2012 - 03:12 PM

View Postbelzi, on 19 February 2012 - 04:59 AM, said:

Jeszcze jedno pytanie pośrednio związane z moim problemem. Czy Waszym zdaniem bezpiecznie i wydajnie jest aby w klasie WebUser zapisać przez $this->setState np. wspomniany przeze mnie departmentId (zalogowany użytkownik przypisany jest do konkretnego wydziału)? W aplikacji będzie wiele rzeczy połączonych właśnie przez deparmentID. Czy lepiej jest zapamiętać jedynie user->id a później już w aplikacji normalnie User::model()->findByPk(ID)->department->id?

I co myślicie o zastosowaniu metody model w klasie WebUser?
public function getModel() 
{
    $user = $this->loadUser(Yii::app()->user->id);
    return $user;
}

protected function loadUser($id=null)
{
    if($this->_model===null)
    {
        if($id!==null)
            $this->_model=User::model()->findByPk($id);
    }
    return $this->_model;
}


Dzięki czemu wywołujemy jedynie przez:

Yii::app()->user->model->department->id;


Cześć,
stosuje podobne rozwiązanie (getModel) do podanego przez Ciebie, z tą różnicą, że cache'uje cały model użytkownika.

Jeśli opierasz na jakiejś danej pobieranej z bazy działanie aplikacji to nie ma sensu pobierać jej przy każdym odświeżeniu strony. Jak najbardziej stosuj takie metody jak set- i getState, właśnie po to są.

d
0

#8 User is offline   belzi 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 4
  • Joined: 18-February 12

Posted 22 February 2012 - 01:52 PM

Dziękuje wszystkim za odpowiedzi, pozdrawiam
0

#9 User is offline   kopecldz 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 86
  • Joined: 20-February 13

Posted 27 February 2013 - 05:23 AM

Chciałbym się dołączyć do zainstniałej sytuacji.

Jak napisał kolega wyżej, udało mi się wyświetlać zadania i projekty użytkownikowi o danym id, który jest przypisany do danego zadania .

Problem w tym , że gdy administrator jest zalogowany również widzi tylko zadania przypisane tylko jemu.
Co zrobić by widział wszystkie zadania, nie tylko te do których jest przypisany .

funkcja task.php:

public function defaultScope()
  {
    return array(
      'condition'=>"user_id='".Yii::app()->user->id."'",
    );
  }

0

#10 User is offline   .viktor. 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 90
  • Joined: 25-August 10
  • Location:Sokołów Podlaski, Poland

Posted 28 February 2013 - 06:40 AM

Jeżeli przypisałeś użytkownikowi "Rolę" to można to zrobić tak:

public function defaultScope(){
  if(Yii::app()->user->checkAccess('administrator')){
    return array();
  }else{
    return array(
      'condition'=>"user_id='".Yii::app()->user->id."'",
    );
  }
}

0

#11 User is offline   kopecldz 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 86
  • Joined: 20-February 13

Posted 01 March 2013 - 04:04 AM

Dzieki, wrzuciłem od razu moduł uprawnień użytkowników , tego mi brakowało.
0

#12 User is offline   kopecldz 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 86
  • Joined: 20-February 13

Posted 04 April 2013 - 07:30 AM

Witam, kolejny raz mam problem z uwierzytelnieniem.

Sprawa wygląda tak, posiadam model Task i Project. W projektach wyświetlam od razu zadania. W kontrolerze Tasku posiadam właśnie funkcje :
public function defaultScope() {
        if (Yii::app()->user->checkAccess('administrator')) {
            return array();
        } else {
            return array(
                'condition' => "user_id='" . Yii::app()->user->id . "'",
            );
        }
    }

W tabeli TASK istnieje user_id, a w projekcie nie , i gdy wyświetla się od razu zadanie w projektach to dostaje error z Joinem :
CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'author_id' in where clause is ambiguous. The SQL statement executed was: SELECT COUNT(DISTINCT `t`.`id`) FROM `project` `t` LEFT OUTER JOIN `user_project` `users_users` ON (`t`.`id`=`users_users`.`project_id`) LEFT OUTER JOIN `user` `users` ON (`users`.`id`=`users_users`.`user_id`) LEFT OUTER JOIN `user` `author` ON (`t`.`author_id`=`author`.`id`) LEFT OUTER JOIN `task` `tasks` ON (`tasks`.`project_id`=`t`.`id`) WHERE (author_id='79') 

Dla tego pewnie ponieważ w projekcie nie posiadam user_id i tutaj problem. Jak to zrobić?
0

#13 User is offline   gadd33 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 22
  • Joined: 15-April 09
  • Location:Opole / Poland

Posted 05 April 2013 - 02:55 AM

Nazwa kolumny author_id w WHERE nie jest jednoznaczna. Czyli masz ją w task i pewnie w project. System nie wie o którą chodzi. Powinieneś poprzedzić ją nazwą tabeli lub aliasem.
0

#14 User is offline   kopecldz 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 86
  • Joined: 20-February 13

Posted 10 April 2013 - 04:51 AM

View Postgadd33, on 05 April 2013 - 02:55 AM, said:

Nazwa kolumny author_id w WHERE nie jest jednoznaczna. Czyli masz ją w task i pewnie w project. System nie wie o którą chodzi. Powinieneś poprzedzić ją nazwą tabeli lub aliasem.

Tak dokładnie .

Ale tu jednak chodzi o "user_id" a nie "author_id" <-błąd występował gdy zamiast "user_id" było wpisane "user_id".

Więc teraz wyrzuca mi :
CDbCommand failed to execute the SQL statement: SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'user_id' in on clause is ambiguous. The SQL statement executed was: SELECT COUNT(DISTINCT `t`.`id`) FROM `project` `t` LEFT OUTER JOIN `user_project` `users_users` ON (`t`.`id`=`users_users`.`project_id`) LEFT OUTER JOIN `user` `users` ON (`users`.`id`=`users_users`.`user_id`) LEFT OUTER JOIN `user` `author` ON (`t`.`author_id`=`author`.`id`) LEFT OUTER JOIN `task` `tasks` ON (`tasks`.`project_id`=`t`.`id`) AND (user_id='49') 


W tym przypadku user_id nie istnieje w "project" , ale istnieje w "task" więc dla czego kolumna "user_id" nie jest jednoznaczna?
0

#15 User is offline   gadd33 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 22
  • Joined: 15-April 09
  • Location:Opole / Poland

Posted 10 April 2013 - 04:56 AM

Ale jest w "user_project". Używaj aliasów - dobry zwyczaj.

W default scope przy user_id brakuje aliasu. Poczytaj tutaj: http://www.yiiframew...n-named-scopes/
0

#16 User is offline   kopecldz 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 86
  • Joined: 20-February 13

Posted 10 April 2013 - 09:27 AM

według tego co podesłałeś :
public function defaultScope() {
        if (Yii::app()->user->checkAccess('administrator')) {
            return array();
        } else {
            return array(
                      'condition' => "$this.'.user_id='" . Yii::app()->user->id . "'",
            );
        }
    }


Wypluwa:
Object of class Project could not be converted to string 

0

#17 User is offline   gadd33 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 22
  • Joined: 15-April 09
  • Location:Opole / Poland

Posted 10 April 2013 - 11:37 AM

Raczej coś takiego:
    'condition' => "{$this->tableAlias}.user_id = '" . Yii::app()->user->id . "'",

0

#18 User is offline   kopecldz 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 86
  • Joined: 20-February 13

Posted 11 April 2013 - 02:46 AM

ublic function defaultScope() {
        if (Yii::app()->user->checkAccess('administrator')) {
            return array();
        } else {
            return array(
                      'condition' => "{$this->users}.user_id = '" . Yii::app()->user->id . "'",
            );
        }
    }


Zrobiłem tak , jako alias dałem relacje z "projektu" i otrzymałem :

Array to string conversion 

0

#19 User is offline   luk1999 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 35
  • Joined: 20-April 11
  • Location:Poland

Posted 11 April 2013 - 04:34 AM

Masz podać alias tabeli (string), a podajesz relację (tablicę). Ogarnij się!

Jak już, to coś w tym rodzaju:
public function defaultScope() {
        if (Yii::app()->user->checkAccess('administrator')) {
            return array();
        } else {
            $tabAlias = ... //Wyciągnij alias z właściwego modelu
            /*
            Coś w tym rodzaju:
            $tabAlias = Task::model()->getTableAlias();
            */
            return array(
                      'condition' => $tabAlias . ".user_id = '" . Yii::app()->user->id . "'",
            );
        }
    }

0

#20 User is offline   kopecldz 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 86
  • Joined: 20-February 13

Posted 11 April 2013 - 05:24 AM

robiłem tak już wcześniej ale za każdym razem wyrzucało mi ze nie ma kolumny user_id w taskach.

Column not found: 1054 Unknown column 't.user_id' in 'where clause'. 

0

Share this topic:


  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users