2013-01-23 51 views
3

我有一個Mojolicious應用程序和認證的橋樑。這是我的場景:
我在數據庫中有一組標準的錯誤響應,我通過傳遞一個值來查詢,比如返回一個帶有詳細錯誤響應的404。數據庫將具有與錯誤相對應的通用細節,而從控制器獲得其他用戶特定的詳細信息,例如ip和用戶名。請參考this link瞭解如何構建錯誤響應。 我有一個幫手,它獲取控制器和錯誤代碼的實例來生成所需的響應。我使用控制器對象通過包含錯誤響應的表的結果集來查詢數據庫。通過控制器,我還可以獲得創建響應所需的用戶特定詳細信息。然後創建響應,並將其發送回控制器,然後以Json形式返回。
我的問題是在註銷時,我設置了$self->session(expires => 1),這會使會話無效。在嘗試再次註銷時,我使用控制器訪問助手構建錯誤響應並將其發送給客戶端。現在任何嘗試訪問任何URI的嘗試都是徒勞的,通過以下檢查進行第一次嘗試。會話不會在Mojolicious

unless($self->session('user')) { 
    my $res = Controller::Helper->error_res($self, 403); 
    $self->render_json($res, status => $res->{httpstatuscode}); 
    return; 
    } 

此檢查工作的第一次,但是當我再次嘗試訪問該資源(任意次數),這個檢查失敗,資源不登錄訪問。當我查看cookie時,會創建一個新的cookie。我在哪裏錯了?處理這些問題最好的辦法是什麼? 助手功能看起來像這樣

error_res{ 
    my($self,$c,$res) = @_; 
    my @arref = $c->db->resultset('Errorcode')->select_row($res); 
    my $ref=$arref[0]; 
    $ref->{user}=$c->session->{user}->{name}; 
    $ref->{request}=$c->req->method."".join("\\",$c->req->url->path); 
    $ref->{time}=scalar localtime(); 
    return $ref; 
} 

哪裏res是和id中,將識別特定錯誤的數據庫。

那麼,它是否與助手的參考控制器仍然可用?當我在幫助程序中找不到$c時,它不起作用。
編輯1:我在這裏錯過了一些觀點,這是正確的方法嗎?
編輯2:我在註銷時使用戶無效。當用戶嘗試再次註銷時,我會返回錯誤並提供有關錯誤的其他信息。但是,在創建有關錯誤的附加信息時,會創建一個沒有用戶信息的新會話。這不會發生,如果我這樣做

unless($self->session('user')) { 
    $self->render_json("message:User has not logged in", status => 403); 
    return; 
} 
+0

我是否知道您對每個請求的會話cookie無效?也許你應該解釋用戶交互流程,我不明白什麼是正確和不正確的行爲。 –

+0

@JoelBerger我編輯了這個問題來回答你的問題,希望它有助於理解這個問題。 –

+0

您的編輯(2)似乎表現得如我所料。當用戶註銷時,(s)他將在新的會話cookie中沒有'user'鍵。我在我的CMS [伽利略](https://github.com/jberger/Galileo/blob/master/lib/Galileo.pm#L111) –

回答

3

所以我想出了答案,奇怪的行爲是由於perl的autovivification功能。它涉及動態創建數據結構。就我而言,我嘗試在

$ref->{user}=$c->session->{user}->{name}; 

打通會話cookie的用戶名當用戶沒有登錄,user密鑰不會在會話設置,但我試圖通過這個鍵就可以name當創建錯誤響應時。這導致創建沒有價值的user。檢查user密鑰是否存在解決了問題。

1

閱讀的評論後,我寧可一定如預期框架行爲。應用程序邏輯可能需要更改(如編輯2所示)。

原因是,會話只是一個hashref,序列化爲JSON,簽名並存儲在cookie中。如果你創建了密鑰,那麼它就在那裏。我不知道還有什麼可以告訴你的。

是的,一個新的會話cookie是在前一個到期之後立即創建的。這對框架是必要的,並且充分預期。

+0

感謝Joel的幫助。我沒有懷疑這個框架。我正在努力弄清楚應用程序中發生了什麼。 –

+0

很高興你明白了,其實我應該想到autoviv –