最近在做一些代碼安全性檢查,使用了Fortify。發現了一些曾經引以為豪的代碼既然會出現高危的錯誤。希望各位達人給予幫助。
設計初衷:共享WebApplicationContext,通過getBean(String beanName)取得對應的bean處理相應的業務邏輯。
public class BaseAction extends Action {
private WebApplicationContext wac;
protected ServletContext context;
public void setServlet(ActionServlet actionServlet) {
super.setServlet(actionServlet);
context = actionServlet.getServletContext();
wac = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
}

protected Object getBean(String beanName) {
return wac.getBean(beanName);
}
}
高危錯誤代碼:
context = actionServlet.getServletContext();
wac = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
錯誤原因分析:BaseAction繼承自Action,單例實現。該類含有屬性:wac與context,在多線程環境下不能保證這兩個屬性的合理邏輯。于是掉入了一個單例模式的陷阱。(請各位達人完善)
解決方法:jdon(banq)給我的回復
設計初衷:共享WebApplicationContext,通過getBean(String beanName)取得對應的bean處理相應的業務邏輯。
















解決方法:jdon(banq)給我的回復
banq:寫的方法是高危,但是看你的方法內容,則沒有關系。 你的方法內容是獲得一個Web項目的一個單例,實際就是Spring容器,而且大部分是讀,而不是讀寫并加。 單例陷阱我已經在以前帖子中說了,只有在單例+寫+同步等操作下才可能死鎖,因為代碼不可控性,今天你注意沒這么做,不代表其他無知的人不這么做,所以,這種singlton會被嚴謹的工具認為是高危,這是正確的。 |
ME:謝謝 banq! 如果需要消除這段高危代碼,需要如何重構. 因為只是存在讀操作,我是否可以把wac與context定義為static(這樣工具不會報錯) 請問這樣改會不會有問題? |
banq:不能用static,這樣Spring容器中所有資源都不能隨著你的WEB項目消失而消失。 主要問題在于你的setServlet(ActionServlet actionServlet)這個方法,這其實是一個初始化工作,試驗在BaseAction的構造方法中首先實現,這樣表示有前有后,可能不會報高危錯誤。 實在不行,做一個懶加載的方法,在這個方法中,檢查一下wac是否為空,如果為,就進行初始化,不為空,就直接返回wac值。 |
去除setServlet方法,在getBean加入,如下,如果還不行,就每次老老實實的用WebApplicationContextUtils獲得Spring實例:![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |