面試問題

一、 pageHelper分頁插件的使用

Mybatisplugin實現了Interceptor接口,能夠在插件中得到執行的sql語句,sql語句中添加limit語句實現分頁。正則表達式

使用原理:pageHelper會使用ThreadLocal獲取同一線程中的變量信息,各個線程之間的Threadlocal不會相互干擾,也就是Thread1中的ThreadLocal1以後獲取到Tread1中的變量的信息,不會獲取到Thread2中的信息因此在多線程環境下,各個Threadlocal之間相互隔離,能夠實現,不一樣thread使用不一樣的數據源或不一樣的Thread中執行不一樣的SQL語句sql

因此,PageHelper利用這一點經過攔截器獲取到同一線程中的預編譯好的SQL語句以後將SQL語句包裝成具備分頁功能的SQL語句,並將其再次賦值給下一步操做,因此實際執行的SQL語句就是有了分頁功能的SQL語句數據庫

二、 防止Sql注入

1) Sql注入攻擊的整體思路跨域

一、 尋找SQL注入的位置緩存

二、 判斷服務器類型和後臺數據庫類型安全

三、 針對不通的服務器和數據庫特色進行SQL注入攻擊 服務器

   方法:cookie

1PreparedStatement

採用預編譯語句集,內置了處理sql注入的能力,只要使用它的setXXX方法傳值便可。session

好處:(1代碼的可讀性和可維護性多線程

     2PreparedStatement可以提升 性能

     3極大的提升了安全性

Sql注入只對sql語句的編譯過程有破壞做用,PreparedStatement已經編譯好了,執行階段只是把輸入串做爲數據處理,不會對sql進行解析,準備所以避免了sql注入的過程。

2使用正則表達式過濾傳入的參數

檢測SQL meta-characters的正則表達式 :

/(\%27)|(\)|(\-\-)|(\%23)|(#)/ix

修正檢測SQL meta-characters的正則表達式 :/((\%3D)|(=))[^\n]*((\%27)|(\)|(\-\-)|(\%3B)|(:))/i

典型的SQL 注入攻擊的正則表達式 :/\w*((\%27)|(\))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix

檢測SQL注入,UNION查詢關鍵字的正則表達式 :/((\%27)|(\))union/ix(\%27)|(\)

檢測MS SQL Server SQL注入攻擊的正則表達式:

/exec(\s|\+)+(s|x)p\w+/ix

3字符串過濾

比較通用的一個方法:

||之間的參數能夠根據本身程序的須要添加)

public static boolean sql_inj(String str)

{

String inj_str = "'|and|exec|insert|select|delete|update|

count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";

String inj_stra[] = split(inj_str,"|");

for (int i=0 ; i < inj_stra.length ; i++ )

{

if (str.indexOf(inj_stra[i])>=0)

{

return true;

}

}

return false;

}

4jsp調用函數判斷是否包含非法字符

防止slqurl注入

public class sql_inj{

public static boolean sql_inj(String str)

{

String inj_str = "'|and|exec|insert|select|delete|update|

count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";

//這裏的東西還能夠本身添加

String[] inj_stra=inj_str.split("\\|");

for (int i=0 ; i < inj_stra.length ; i++ )

{

if (str.indexOf(inj_stra[i])>=0)

{

return true;

}

}

return false;

}

}

5jsp頁面判斷代碼

使用js客戶端進行不安全字符的屏蔽,檢查是否含有」‘」,」\\」,」/」

Mybatis中模糊查詢防止sql注入

#{xxx},使用的是PreparedStatement,會有類型轉換,因此比較安全;

${xxx},使用字符串拼接sql注入的問題

select * from t_user where name like concat('%', #{name}, '%')  

 

 

四、 單點登陸

用戶的一次登陸就能獲得其餘全部系統的信任,那麼關鍵的是如何產生和存儲那個信任

   存儲信任

   驗證信任

集羣環境登陸:

第一種:以cookie做爲憑證媒介

存在的問題:Cookie不安全

            不能跨域實現免登錄

解決的辦法:1.Cookie進行加密(源碼不泄露的狀況下

Cookie的加密和解密:DES加密和解密、MD5加密和解密(不可逆工具類直接用

       (DES加密的原理:使用了一個56位的密鑰以及附加的8位奇偶校驗位,產生最大64位的分組大小。迭代的分組密碼,將加密的文本分紅了兩份,使用子密鑰對其中一半應用循環功能,而後將輸出與另一半進行「異或」運算;接着進行交換這兩半,一直循環下去)

  1. 跨域實現免登錄:配置session共享
    1. 使用Tomcat自身的同步機制複製session到集羣中的其餘服務器

Tomcat的同步機制是廣播形式,也就是說集羣中全部Tomcat都是相同的session信息,可是這種狀況下,Tomcat越多,效率就會越低,官方給出的最佳集羣數量是5Tomcat

   2.使用緩存服務器集中存儲session信息達到session共享需求。無論在那臺服務器登陸成功以後,都會將session信息保存在統一的Redis緩存服務器中,獲取用戶登陸信息。

 

存儲信任

驗證信任

只要解決了以上的問題,達到了開頭講得效果就能夠說是SSO。最簡單實現SSO的方法就是用Cookie,實現流程以下所示:

 

 

 

否則發現以上的方案是把信任存儲在客戶端的Cookie裏,這種方法雖然實現方便但立馬會讓人質疑兩個問題:

 

Cookie不安全

不能跨域免登

對於第一個問題通常都是經過加密Cookie來處理,第二個問題是硬傷,其實這種方案的思路的就是要把這個信任關係存儲在客戶端,要實現這個也不必定只能用Cookie,用flash也能解決,flash的Shared Object API就提供了存儲能力。

 

通常說來,大型系統會採起在服務端存儲信任關係的作法,實現流程以下所示:

 

以上方案就是要把信任關係存儲在單獨的SSO系統(暫且這麼稱呼它)裏,提及來只是簡單地從客戶端移到了服務端,但其中幾個問題須要重點解決:

 

如何高效存儲大量臨時性的信任數據

如何防止信息傳遞過程被篡改

如何讓SSO系統信任登陸系統和免登系統

對於第一個問題,通常能夠採用相似與memcached的分佈式緩存的方案,既能提供可擴展數據量的機制,也能提供高效訪問。對於第二個問題,通常採起數字簽名的方法,要麼經過數字證書籤名,要麼經過像md5的方式,這就須要SSO系統返回免登URL的時候對需驗證的參數進行md5加密,並帶上token一塊兒返回,最後需免登的系統進行驗證信任關係的時候,需把這個token傳給SSO系統,SSO系統經過對token的驗證就能夠辨別信息是否被改過。對於最後一個問題,能夠經過白名單來處理,說簡單點只有在白名單上的系統才能請求生產信任關係,同理只有在白名單上的系統才能被免登陸。

 

 

一、大家用dubbo是怎麼設計接口的?參數返回值是什麼?爲何這麼設計?

硬件經過通信模塊TCP協議傳過一個數據包,你須要接受並解析,解析規則已有

2、在開發過程當中,多個使用zookeeper怎麼解決端口衝突的問題

3、插入數據的時候,若是有重複的就變成修改,怎麼實現

ON DUPLICATE KEY UPDATE(當出現DUPLICATE KEY主鍵重複錯誤的時候觸發Update操做,固然要求就是表在設計的時候必定要有主鍵primary key

$sql = "insert into weixin_user(wx_id, wx_name, wx_state, wx_info, wx_lasttime) values ('$wx_id', '$wx_name', '$wx_state', '$wx_info', NOW()) ON DUPLICATE KEY UPDATE wx_name='$wx_name', wx_state = '$wx_state', wx_info = '$wx_info', wx_lasttime = NOW();";

5Dubbo底層原理:

  1. client一個線程調用遠程接口,生成一個惟一的ID(好比一段隨機字符串,UUID等),Dubbo是使用AtomicLong(原子變量,加了同步鎖的)從0開始累計數字的
  2. 將打包的方法調用信息(如調用的接口名稱,方法名稱,參數值列表等),和處理結果的回調對象callback,所有封裝在一塊兒,組成一個對象object
  3. 向專門存放調用信息的全局ConcurrentHashMap裏面put(ID, object)
  4. ID和打包的方法調用信息封裝成一對象connRequest,使用IoSession.write(connRequest)異步發送出去
  5. 當前線程再使用callback的get()方法試圖獲取遠程返回的結果,在get()內部,則使用synchronized獲取回調對象callback的鎖, 再先檢測是否已經獲取到結果,若是沒有,而後調用callback的wait()方法,釋放callback上的鎖,讓當前線程處於等待狀態。
  6. 服務端接收到請求並處理後,將結果(此結果中包含了前面的ID,即回傳)發送給客戶端,客戶端socket鏈接上專門監聽消息的線程收到消息,分析結果,取到ID,再從前面的ConcurrentHashMap裏面get(ID),從而找到callback,將方法調用結果設置到callback對象裏。
  7. 監聽線程接着使用synchronized獲取回調對象callback的鎖(由於前面調用過wait(),那個線程已釋放callback的鎖了),再notifyAll(),喚醒前面處於等待狀態的線程繼續執行(callback的get()方法繼續執行就能拿到調用結果了),至此,整個過程結束。
相關文章
相關標籤/搜索