iT邦幫忙

0

[php] 表單簽核

php
  • 分享至 

  • xImage

各位大大好:

現在只有把問卷表單寫好,使用者按送出啟動流程,可寫入資料庫,只是不懂要如何將要簽核的流程用資料庫呈現跟如何用網頁表現出來再用phpmailer送給下一關審核者
ex:
使用者->承辦人->課長->主任
表單資料是否用一個表格(流水號當主鍵),簽核人員的流程又一個表格(裡面要記錄誰簽跟時間、是否同意、跟備註)跟網頁頁面去點選簽核單。

想問以上這些是否用php就可以完成呢?

沒有頭緒,不知有沒有程式碼可以參考之類的,還請大家不吝指教 謝謝

player iT邦大師 1 級 ‧ 2019-10-20 01:42:02 檢舉
用eMail去跑workflow? 這樣風險會很高喔
因為SMTP有可能會掉信
當下一個簽核者沒收到原本預期該收到的eMail的話
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
1
dragonH
iT邦超人 5 級 ‧ 2019-10-18 21:49:54

想問以上這些是否用php就可以完成呢?

應該可以

但是你要的功能可以很簡單

也可以很複雜

使用者按送出啟動流程

寫入資料庫並產生公文單次存取ID(e.g. JWT)

將網址利用 phpmailer 傳給 要簽核的人(e.g. https://127.0.0.1/sign?code=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c)

簽核者可能經過認證後打開公文並簽核(所以可能要有個使用者管理系統), 送出後寫入資料庫並更新單次存取ID

再發給下一個簽核者

以此類推

我想到的最簡單大概就這樣

看更多先前的回應...收起先前的回應...
mayyola iT邦研究生 2 級 ‧ 2019-10-18 22:45:27 檢舉

d大您好:
剛剛搜尋看JWT範例,真的不知道如何應用(第一次接觸),我再查查看
我的想法如下,這樣不知道有沒有問題或那裡有誤 謝謝
https://ithelp.ithome.com.tw/upload/images/20191018/20097057Tbqk0xpW75.png

dragonH iT邦超人 5 級 ‧ 2019-10-18 23:22:10 檢舉

mayyola

這樣不知道有沒有問題或那裡有誤

基本上應該不會到 "誤"

只有好不好 方不方便而已

有的時候也可能實際 run 才會發現哪裡不好才改

我的想法如下

1 . 表單A完成, 同時也指定那些人須簽核然後寫到同一個資料表

e.g.
{
    title: '......',
    content: '.......',
    signer: [
        {
            name: '...',
            reply: '',
            time: '',
            status: '0',
        },
        {
            name: '...',
            reply: '',
            time: '',
            status: '0',
        },        
    ],
    status: '0',
    accessCode: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c',
}

2 .
將網址依序發給簽屬者

e.g. http://127.0.0.1?code=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

簽屬者進入網址須通過認證(e.g. 登入)

(可以把接下來要簽的人帳號簽在 jwt 的 payload 裡

這樣登入時就能檢查是不是該他簽)

3 .
簽完送出後

檢查此公文是否全部簽完(e.g. signer 全部的 status 為 1)

簽完就...簽完

沒簽完就繼續上面的操作

每次簽完更新 accessCode

依此類推

至於你想要有那些資料就看你

jwt 最大的用意是不容易偽造

裡面可以放一些非機敏資料

e.g. 下一個簽核者帳號

froce iT邦大師 1 級 ‧ 2019-10-20 03:27:21 檢舉

JWT的安全性不會比session好喔。
JWT上面除了第3段簽名是有經過加密,其他攜帶的資訊都是base64...
下一個簽核者帳號應該要把他當機敏資料,放在資料庫內,萬一把你JWT第2段解碼後,改掉,然後系統撰寫者又沒注意到這部分,只檢查JWT token是否相符,但是下一個簽核者是靠明碼JSON傳送...

dragonH iT邦超人 5 級 ‧ 2019-10-20 12:27:00 檢舉

froce

第三段部分的簽名

不是以 jwt header + jwt payload + secret來簽的嗎

自己改內容而簽名沒變的話

後端驗證不會過吧/images/emoticon/emoticon19.gif

還是我對 jwt 有什麼誤會了XD

不過應該也不會完全以 jwt 來當作驗證的依據就是

froce iT邦大師 1 級 ‧ 2019-10-20 17:04:26 檢舉

不是以 jwt header + jwt payload + secret來簽的嗎

是,但是你的playload包含了「下個簽核者」這個可能會變動的欄位啊。
JWT的應用情景適合在你的playload為「一登入就固定下來」的狀況。
你想想,今天你的JWT token本來還沒過期,然後因為有時候使用者要改「下個簽核者」(簽文加會也很正常啊),那你的token要不要改?改了你又用spa,瀏覽器基本上不刷新,會不會造成token原本沒過期,你得讓使用者強制更新token,或是沿用舊token,然後因為下個簽核者不同,造成你欄位出錯的狀況,這些很容易就被忽略掉,而且通常改動一下,就很難改。

https://medium.com/mr-efacani-teatime/%E6%B7%BA%E8%AB%87jwt%E7%9A%84%E5%AE%89%E5%85%A8%E6%80%A7%E8%88%87%E9%81%A9%E7%94%A8%E6%83%85%E5%A2%83-301b5491b60e

最近在寫一個專案,就是打算做完全的前後端分離SPA(順便練VUE.js),並試用JWT。
發現最佔我心力的是認證機制,需要很小心的去設計後端DRF(django rest framework)的資料庫權限,本來依靠session去判斷身份的功能都不能用,原本可以輕易達成使用者和管理者的js lib在後端輸出不同的結果,都不能用,前端其實可以輕鬆的得到原本管理者使用的lib,除非你真的對這種認證機制的不可靠有相當的理解,要不然很難設計出具有良好安全性的系統。

淺水員 iT邦大師 6 級 ‧ 2019-10-20 17:36:06 檢舉

例如:C的表單要給A跟B簽核,而B除了寫上自己的資料後同時也偽造了A的簽核。
為了避免這類狀況,好像還是得靠 session 跟資料庫紀錄狀態。

mayyola iT邦研究生 2 級 ‧ 2019-10-20 17:48:33 檢舉

F大跟h大說的jwt 應用我沒接觸過,不知到要應用在哪?我的想法是每個簽核者都要登入系統,每筆簽核單都在資料庫下個簽核的是誰..簽核者登入後用session(“name”)去列出要簽核的單子,簽核者可以依依點選看內容並簽核,不知這種方式是否可行,謝謝

dragonH iT邦超人 5 級 ‧ 2019-10-20 18:35:17 檢舉

playload包含了「下個簽核者」這個可能會變動的欄位啊

froce

我大概了解你的看法了

不過我預設 jwt 在這的場景

大概就類似公文識別ID的用途

大概就是

User 透過連結存取

後端驗證是否為合法 token

以 token 搜尋 database 取得此筆公文的相關資訊

進行接下來的操作(到此處 jwt token 就沒用途了)

所以我才沒有提什麼 jwt blacklist 之類的東西

因為我只是把它當成 公文ID 使用

真正該誰簽或者相關的東西

都還是以我一開始說的那個 database 為主

就算 User 丟一個過期的 token 過來

驗證會過

但 database 會找不到此筆公文

(因為原本的 token 可能因已經簽完或者加簽等操作變更 token)

不過這倒也提醒我就是

jwt 當公文識別ID可能不太好(e.g. 日後想查詢此公文之類的)

最近在寫一個專案,就是打算做完全的前後端分離SPA...

改用 jwt 真的會讓以前很簡單的東西變得有點麻煩/images/emoticon/emoticon01.gif

e.g.

  • 想要 user pending 超過 30 分鐘就登出

  • 限制單一登入

等等..

沒辦法像以前用 session 那麼直覺簡單


淺水員

例如:C的表單要給A跟B簽核..

你好像誤會了XD

這些東西都不會放在 jwt 裡啦XD

應該是說

真正的紀錄都還是在 database 裡


mayyola

你可能需要先把流程完整的列出來

然後考慮到有可能發生的情況

e.g.

如何知道開啟此公文的就是接下來要簽的人

那個階段可能會加簽

有沒有可能有代簽的情況

如果公文退回要如何處理 等...

把這些情況與解決方法列出來後

再轉以 coding 的方式表現與思考會比較有幫助且有效率

jwt 只是個工具而已

不熟或者不想用其實也沒差XD/images/emoticon/emoticon07.gif

froce iT邦大師 1 級 ‧ 2019-10-20 18:59:20 檢舉

我就是覺得你搞不定JWT才寫上面那些的,D大的話我相信他絕對有能力搞定,我才不會提醒他。XD

基本上你說的ok,但我見到公家機關的公文系統,他的流程設定是由主辦人一開始設定的,剩下的有需要的再去進行改會、加會等工作。
這部分要看使用者實際需求才能作,如果要設計到這麼正式,你目前的設計就行不通。

真正的公文系統在流程這部分才是最難搞的。

froce iT邦大師 1 級 ‧ 2019-10-20 19:09:28 檢舉

想要 user pending 超過 30 分鐘就登出

這簡單啊,反正你取資料都要用JWT,過時就登出就好。
麻煩的反而是你想要長時間不過期。(用雙token做refresh的狀況)

限制單一登入

你還是可以和session並用。
或是在第一次用帳號密碼登入的時候把登入ip做JWT的playload,然後驗證時檢查。當然這不是非常安全的方法,但聊勝於無啦。

mayyola iT邦研究生 2 級 ‧ 2019-10-20 21:03:44 檢舉

我剛剛找了幾個有關jwt的文,user跟password登入後跟資料庫認證,再將部分資料與公文ID經過jwt產生加密的連結,寫入資料庫..D大的想法是這樣對嗎?

dragonH iT邦超人 5 級 ‧ 2019-10-20 21:34:10 檢舉

mayyola

我剛剛找了幾個有關jwt的文,user跟password登入後跟資料庫認證

如果你不是做前後端分離的話

那就先把 jwt 放一邊

乖乖用 session 做吧

會比較單純

不太需要糾結在 jwt 上

再將部分資料與公文ID經過jwt產生加密的連結

嚴格來說

jwt 不算加密

就像 froce 大說的

他前兩個部分只是 base64

dragonH iT邦超人 5 級 ‧ 2019-10-20 21:45:53 檢舉

...(用雙token做refresh的狀況)

refresh token 的作法好像蠻常見的

不過這樣一來

就勢必會需要 blacklist 來讓舊的 token 提早失效

然後考慮到多個 request 併發的情況

e.g. 短時間發 10 request, 可能在第一個 request 時

剛好觸發 refresh 的條件然後 refresh token

但是這 10 個送到後端的 token

都是同一個

如果只是 refresh 完後讓舊的 token 失效

可能會造成後面的 request 都變得不合法

這時會需要一個 expire time

讓進入 blacklist 的 token

短時間之內還有效

froce iT邦大師 1 級 ‧ 2019-10-21 08:29:42 檢舉

JWT只是簽名而已,不是加密。

然後考慮到多個 request 併發的情況
e.g. 短時間發 10 request, 可能在第一個 request 時
剛好觸發 refresh 的條件然後 refresh token
但是這 10 個送到後端的 token...

沒有這麼頻繁的refresh操作啦。
你在要CRUD前做一次refresh就行了。
像我目前寫的專案,就是用vuex存refresh的action,每次要CRUD前確保access token是有效的,然後再一次做複數的POST/PUT

this.$store.dispatch("refresh")

let put = edited.filter(p => p.url)
        .map( p => {
          this.$http
            .put(p.url)
            .set("Authorization", 'Bearer '+ this.$store.state.accessToken)
            .send(p)
            .then( success => {
              ...
            }, error => {
              ...
            })
        })

refresh:

superagent.post(baseURL + "/api-token-refresh/")
          .send({
            refresh: state.refreshToken
          })

access和refresh token的關係是,假設access 5分鐘過期,refresh 1天過期。
然後我每5分鐘就post refresh token,返回新的access token,供認證。
要不然就是不管他什麼時候過期,反正要CRUD跟後端要資源都更新一次。

有興趣可以研究一下simplejwt這個DRF套件:
https://github.com/davesque/django-rest-framework-simplejwt

他說明寫得很簡單,但光是認證要整合AD我就爬了好久的原始碼,後來才發現他把auth相關的backend都關掉了...Orz

dragonH iT邦超人 5 級 ‧ 2019-10-21 10:48:31 檢舉

喔喔

大概瞭解了

不過我指的 pending 30 分鐘

是指距上次操作 30 分鐘

不是 token 30分鐘 過期就是XD /images/emoticon/emoticon07.gif

就是用vuex存refresh的action,每次要CRUD前確保access token是有效的

這樣的做法會不會有

trigger action 時

還沒達到 refresh 的條件(e.g. token 還沒過期)

所以沒更新 token 然後發了 request

可是實際 request 到達時

所帶的 token 已經過期

這種情況

froce iT邦大師 1 級 ‧ 2019-10-21 13:17:00 檢舉

不過我指的 pending 30 分鐘
是指距上次操作 30 分鐘

這,可能就得去查上次刷新token時間,然後在前端登出。
以我目前寫的心得是前端logout反而好做,把token都清掉就行。

你不用檢查access token過期了沒啊,反正你post refresh token他就吐新的access token給你,又一個5分鐘。XD
而且5分鐘對對你只發送 http request 應該綽綽有餘,會過期的話可能等到接收response的時候吧。
倒是發送大檔案的時候就真的得考慮這問題了,目前沒實驗過。

dragonH iT邦超人 5 級 ‧ 2019-10-21 14:30:33 檢舉

了解

感謝 froce大 經驗談
/images/emoticon/emoticon42.gif/images/emoticon/emoticon42.gif/images/emoticon/emoticon42.gif

0
小魚
iT邦大師 1 級 ‧ 2019-10-18 22:07:09

我覺得,
你要學的可能還很多,
不過一般比較正常的公司應該會有美工出圖給你吧.

mayyola iT邦研究生 2 級 ‧ 2019-10-18 22:49:06 檢舉

小魚大您好:
是的,自從寫過一個繳費網頁(只是產生繳費單跟流水號)覺得還有很多不足,目前也只有寫過表單填入,如果還想要更深一步不知道要如何從哪裡學習(只看過php+mysql書籍、asp語法略懂)..it幫幫忙有些文章跟問答有些都看不懂,謝謝

小魚 iT邦大師 1 級 ‧ 2019-10-19 08:35:15 檢舉

我覺得,
如果真的想要專精,
就要找相關工作,
而且要找有前輩能夠教你的地方,
學起來才會快.

froce iT邦大師 1 級 ‧ 2019-10-20 03:30:48 檢舉

不會啊,像我就是完全沒前輩練起來的。
有個目標就很快,只是要學會自己找到對的方法和資源。

1
Darwin Watterson
iT邦好手 1 級 ‧ 2019-10-19 00:00:27

簽核一般不都設計成勾選選項, 相關的人勾一勾就放行 /images/emoticon/emoticon19.gif
https://ithelp.ithome.com.tw/upload/images/20191018/20109107AiqOwwnwrs.png
搞得那麼複雜難不成是傳說中的政府外包案,還要印出來按官防存查 ?
/images/emoticon/emoticon39.gif
說好的環保無紙化咧 .../images/emoticon/emoticon38.gif

2
ckp6250
iT邦好手 1 級 ‧ 2019-10-19 16:58:23

  【簽核】這個動作,可以簡單到不行,也能複雜到沒命。

  我做過加班和請假的簽核流程,甲要請假,填好假單之表單送出,自然要有上一級的主管來簽核,問題是,要送給那一個主管呢?甲的直屬主管可能自己也請假,於是,這張假單要自動轉發給代理主管或更上層的主管,但,萬一代理主管或更上層主管也請假呢?又要再向上推導~~~

  該公司採用三級審批制度,於是,每一級都會遇到同樣的問題。

  所以,到底該怎麼做【簽核】的流程,沒有標準答案,有些公司會把事情搞得很複雜,要怎麼規劃,如同 dragonH 大大所言,有的時候也可能實際 run 才會發現哪裡不好才改

0
阿展展展
iT邦好手 1 級 ‧ 2019-10-20 01:26:33

同意樓上幾位講的
【簽核】這個動作,可以簡單到不行,也能複雜到沒命。
只要打勾勾就可以。
可以很簡單也可以很複雜。


現在看起來

  1. 你的需求並沒有很明確:
    a. 你只提供了一個可能會發生的情境,但同級間的簽核呢?大家一起「已閱」「已閱」....
    b. 由下往上是要層層簽,那由上往下只要看過,但不需要簽核
    c. .... etc

  2. 你的工具並沒有很多:
    想要純PHP解決,如果要包含介面的部分的話勢必要有一點點稍微 css ,如果稍微功能再更複雜一點點,不用框架去解決其實用原生刻會蠻費(ㄊㄨㄥˋ)工(ㄎㄨˇ)夫的

所以...可以再更明確一點,你想要做到什麼程度的「簽核」系統
你希望以那些「工具」來達成這個願望
你預計「多久」完成這個系統

這樣方向會更明確一點點

以上淺見

mayyola iT邦研究生 2 級 ‧ 2019-10-20 17:52:55 檢舉

我目前會的,只有php css jquery Ajax 但我覺得我會的都是基礎,想說三個月至少能完成由上到下,暫不考慮有加會的情況,謝謝

1
froce
iT邦大師 1 級 ‧ 2019-10-20 03:37:34

表單資料是否用一個表格(流水號當主鍵),簽核人員的流程又一個表格(裡面要記錄誰簽跟時間、是否同意、跟備註)跟網頁頁面去點選簽核單。

其實差不多是這樣沒錯。不過的確像上面2位說的,要複雜可以很複雜。
正常流程完了,然後偶爾會有要修改流程的、要加會的、要補加會的、要先呈核後加會的...
這還是線性而已,有些還會要求要同時加會的...

我要發表回答

立即登入回答